diff --git a/pom.xml b/pom.xml index d173321..d7910f7 100644 --- a/pom.xml +++ b/pom.xml @@ -96,6 +96,7 @@ hutool-all 5.8.4 + diff --git a/src/main/java/com/aos/fileidentify/AosFileIdentifyApplication.java b/src/main/java/com/aos/fileidentify/AosFileIdentifyApplication.java index 3f3fbe9..024627f 100644 --- a/src/main/java/com/aos/fileidentify/AosFileIdentifyApplication.java +++ b/src/main/java/com/aos/fileidentify/AosFileIdentifyApplication.java @@ -3,9 +3,25 @@ package com.aos.fileidentify; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:29 + * @since 0.0.1 + */ @SpringBootApplication public class AosFileIdentifyApplication { + /** + * Main + * + * @param args args + * @since 0.0.1 + */ public static void main(String[] args) { SpringApplication.run(AosFileIdentifyApplication.class, args); } diff --git a/src/main/java/com/aos/fileidentify/config/Knife4jConfiguration.java b/src/main/java/com/aos/fileidentify/config/Knife4jConfiguration.java index e5cacf7..6af32d1 100644 --- a/src/main/java/com/aos/fileidentify/config/Knife4jConfiguration.java +++ b/src/main/java/com/aos/fileidentify/config/Knife4jConfiguration.java @@ -24,6 +24,12 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; @EnableSwagger2 public class Knife4jConfiguration { + /** + * Default api 2 + * + * @return the docket + * @since 0.0.1 + */ @Bean(value = "defaultApi2") public Docket defaultApi2() { Docket docket = new Docket(DocumentationType.SWAGGER_2) diff --git a/src/main/java/com/aos/fileidentify/controller/FileIdentifyController.java b/src/main/java/com/aos/fileidentify/controller/FileIdentifyController.java index 9ed2a64..7006450 100644 --- a/src/main/java/com/aos/fileidentify/controller/FileIdentifyController.java +++ b/src/main/java/com/aos/fileidentify/controller/FileIdentifyController.java @@ -26,6 +26,7 @@ import lombok.AllArgsConstructor; @AllArgsConstructor public class FileIdentifyController { + /** File identify service */ private final FileIdentifyService fileIdentifyService; diff --git a/src/main/java/com/aos/fileidentify/converter/SerializableStringConverter.java b/src/main/java/com/aos/fileidentify/converter/SerializableStringConverter.java new file mode 100644 index 0000000..bc13fb5 --- /dev/null +++ b/src/main/java/com/aos/fileidentify/converter/SerializableStringConverter.java @@ -0,0 +1,60 @@ +package com.aos.fileidentify.converter; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import java.io.Serializable; + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description: 用于EsayExel中转换实现{@link Serializable}的字段,将{@link Serializable#toString()}输出到excel中。 + *

+ * + * @author xianzhiping + * @version 2.3.0 + * @email "mailto:xianzhiping@fkhwl.com" + * @date 2022.01.19 16:49 + * @since 2.3.0 + */ +public class SerializableStringConverter implements Converter { + /** + * Support java type key + * + * @return the class + * @since 1.0.0 + */ + @Override + public Class supportJavaTypeKey() { + return Serializable.class; + } + + /** + * Support excel type key + * + * @return the cell data type enum + * @since 1.0.0 + */ + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + /** + * Convert to excel data + * + * @param value value + * @param contentProperty content property + * @param globalConfiguration global configuration + * @return the cell data + * @throws Exception exception + * @since 1.0.0 + */ + @Override + public WriteCellData convertToExcelData(Serializable value, ExcelContentProperty contentProperty, + GlobalConfiguration globalConfiguration) throws Exception { + return new WriteCellData<>(String.valueOf(value)); + } +} diff --git a/src/main/java/com/aos/fileidentify/entity/BaseEntity.java b/src/main/java/com/aos/fileidentify/entity/BaseEntity.java index c4310fb..169a0bf 100644 --- a/src/main/java/com/aos/fileidentify/entity/BaseEntity.java +++ b/src/main/java/com/aos/fileidentify/entity/BaseEntity.java @@ -4,15 +4,29 @@ import lombok.Data; import java.util.Date; +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:29 + * @since 0.0.1 + */ @Data public class BaseEntity { + /** Id */ private String id; + /** Deleted */ private String deleted; + /** Create time */ private Date create_time; + /** Update time */ private Date update_time; } diff --git a/src/main/java/com/aos/fileidentify/entity/EmployeeApproval.java b/src/main/java/com/aos/fileidentify/entity/EmployeeApproval.java index bb141c6..b7fdae7 100644 --- a/src/main/java/com/aos/fileidentify/entity/EmployeeApproval.java +++ b/src/main/java/com/aos/fileidentify/entity/EmployeeApproval.java @@ -5,55 +5,89 @@ import lombok.Data; import javax.validation.constraints.NotNull; +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:29 + * @since 0.0.1 + */ @Data public class EmployeeApproval extends BaseEntity { + /** Employee key */ private String employeeKey; + /** Name */ @ExcelProperty("姓名") @NotNull private String name; + /** Age */ @ExcelProperty("年龄") private String age; + /** Department */ @ExcelProperty("部门") private String department; + /** Project */ @ExcelProperty("项目") private String project; + /** Branch */ @ExcelProperty("单位") private String branch; + /** Current position */ @ExcelProperty("现任职务") private String currentPosition; + /** Gender */ @ExcelProperty("性别") private String gender; + /** Ethnic */ @ExcelProperty("民族") private String ethnic; + /** Birth */ @ExcelProperty("出生年月") private String birth; + /** Highest education */ @ExcelProperty("最高学历") private String highestEducation; + /** Full time edu qualifications */ @ExcelProperty("全日制教育学历学位") private String fullTimeEduQualifications; + /** Full time edu institutions */ @ExcelProperty("全日制教育毕业院校及专业") private String fullTimeEduInstitutions; + /** On job edu qualifications */ @ExcelProperty("在职教育学历学位") private String onJobEduQualifications; + /** On job edu institutions */ @ExcelProperty("在职教育毕业院校及专业") private String onJobEduInstitutions; + /** Join party time */ @ExcelProperty("入党时间") private String joinPartyTime; + /** Join work time */ @ExcelProperty("参加工作时间") private String joinWorkTime; + /** Current position time */ @ExcelProperty("任现职时间") private String currentPositionTime; + /** Current rank time */ @ExcelProperty("任现职级时间") private String currentRankTime; + /** Managers type */ @ExcelProperty("经理人性质") private String managersType; + /** Is concurrently */ @ExcelProperty("兼职") private String isConcurrently; + /** Appointment documents */ @ExcelProperty("任命文件") private String appointmentDocuments; + /** Post type */ @ExcelProperty("岗位类型") private String postType; + /** Remark */ private String remark; diff --git a/src/main/java/com/aos/fileidentify/entity/EmployeeChange.java b/src/main/java/com/aos/fileidentify/entity/EmployeeChange.java index 28defde..0c308b4 100644 --- a/src/main/java/com/aos/fileidentify/entity/EmployeeChange.java +++ b/src/main/java/com/aos/fileidentify/entity/EmployeeChange.java @@ -5,13 +5,30 @@ import lombok.Data; import java.util.Date; +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:29 + * @since 0.0.1 + */ @Data public class EmployeeChange extends BaseEntity { + /** Employee key */ private String employee_key; + /** Change type */ private String change_type; + /** Source branch */ private String source_branch; + /** Transfer branch */ private String transfer_branch; + /** Change time */ private Date change_time; + /** Change branch */ private String change_branch; + /** Change position */ private String change_position; } diff --git a/src/main/java/com/aos/fileidentify/entity/dto/EmployeeChangeDTO.java b/src/main/java/com/aos/fileidentify/entity/dto/EmployeeChangeDTO.java index 7d4f05f..f8e1bba 100644 --- a/src/main/java/com/aos/fileidentify/entity/dto/EmployeeChangeDTO.java +++ b/src/main/java/com/aos/fileidentify/entity/dto/EmployeeChangeDTO.java @@ -6,51 +6,83 @@ import lombok.Data; import javax.validation.constraints.NotNull; import java.util.Date; +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:29 + * @since 0.0.1 + */ @Data public class EmployeeChangeDTO { + /** Employee key */ private String employee_key; + /** Change type */ @ExcelProperty("异动类型") private String change_type; + /** Change time */ @ExcelProperty("异动时间") private Date change_time; + /** Change branch */ @ExcelProperty("拟任免部门") private String change_branch; + /** Change position */ @ExcelProperty("拟任免职务") private String change_position; + /** Name */ @ExcelProperty("姓名") @NotNull private String name; + /** Branch */ @ExcelProperty("单位") private String branch; + /** Current position */ @ExcelProperty("原职务") private String currentPosition; + /** Gender */ @ExcelProperty("性别") private String gender; + /** Ethnic */ @ExcelProperty("民族") private String ethnic; + /** Birth */ @ExcelProperty("出生年月") private String birth; + /** Full time edu qualifications */ @ExcelProperty("全日制教育学历学位") private String fullTimeEduQualifications; + /** Full time edu institutions */ @ExcelProperty("全日制教育毕业院校及专业") private String fullTimeEduInstitutions; + /** On job edu qualifications */ @ExcelProperty("在职教育学历学位") private String onJobEduQualifications; + /** On job edu institutions */ @ExcelProperty("在职教育毕业院校及专业") private String onJobEduInstitutions; + /** Age */ @ExcelProperty("年龄") private String age; + /** Join party time */ @ExcelProperty("入党时间") private String joinPartyTime; + /** Join work time */ @ExcelProperty("参加工作时间") private String joinWorkTime; + /** Managers type */ @ExcelProperty("经理人性质") private String managersType; + /** Is concurrently */ @ExcelProperty("兼职") private String isConcurrently; + /** Appointment documents */ @ExcelProperty("任命文件") private String appointmentDocuments; + /** Post type */ @ExcelProperty("岗位类型") private String postType; diff --git a/src/main/java/com/aos/fileidentify/service/impl/FileIdentifyServiceImpl.java b/src/main/java/com/aos/fileidentify/service/impl/FileIdentifyServiceImpl.java index 5a28e25..9bfc6e7 100644 --- a/src/main/java/com/aos/fileidentify/service/impl/FileIdentifyServiceImpl.java +++ b/src/main/java/com/aos/fileidentify/service/impl/FileIdentifyServiceImpl.java @@ -69,6 +69,12 @@ public class FileIdentifyServiceImpl implements FileIdentifyService { } + /** + * Process excel + * + * @param file file + * @since 0.0.1 + */ @Override public void processExcel(MultipartFile file) { Assert.notNull(file, "上传数据为空"); diff --git a/src/main/java/com/aos/fileidentify/util/ExcelUtils.java b/src/main/java/com/aos/fileidentify/util/ExcelUtils.java new file mode 100644 index 0000000..e89c2a7 --- /dev/null +++ b/src/main/java/com/aos/fileidentify/util/ExcelUtils.java @@ -0,0 +1,306 @@ +package com.aos.fileidentify.util; + +import com.google.common.collect.Lists; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.support.ExcelTypeEnum; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.aos.fileidentify.converter.SerializableStringConverter; +import com.aos.fileidentify.util.function.DataSupplier; +import com.baomidou.mybatisplus.core.metadata.IPage; + +import com.baomidou.mybatisplus.core.toolkit.StringPool; + + +import org.springframework.http.HttpHeaders; +import org.springframework.util.Assert; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import javax.servlet.http.HttpServletResponse; + +import lombok.SneakyThrows; +import lombok.experimental.UtilityClass; + + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:29 + * @since 0.0.1 + */ +@UtilityClass +public class ExcelUtils { + /** + * excel导出content-type + */ + public static final String EXCEL_CONTENT_TYPE = "application/vnd.ms-excel"; + /** + * 每个工作表默认行数 + */ + private static final int DEFAULT_EXCEL_SHEET_SIZE = 200000; + /** + * 默认查询数据sql每页条数 + */ + private static final int DEFAULT_PAGE_LIMIT = 20000; + + /** + * 默认一次导出最大条数 + */ + private static final int DEFAULT_MAX_EXPORT_SIZE = 20000; + + /** + * 查询数据sql每页条数 + */ + private static int pageLimit = DEFAULT_PAGE_LIMIT; + + /** + * 是否限制excel导出条数 + */ + private static boolean limitExportSize = true; + /** + * excel最大导出条数 + */ + private static int maxExportSize = DEFAULT_MAX_EXPORT_SIZE; + + /** + * 初始化 + * + * @param pageLimit page limit + * @param limitExportSize 是否限制导出条数 + * @param maxExportSize max size + * @since 2.3.0 + */ + public static void init(Integer pageLimit, boolean limitExportSize, Integer maxExportSize) { + ExcelUtils.limitExportSize = limitExportSize; + ExcelUtils.pageLimit = pageLimit != null ? pageLimit : DEFAULT_PAGE_LIMIT; + ExcelUtils.maxExportSize = maxExportSize != null ? maxExportSize : DEFAULT_MAX_EXPORT_SIZE; + Assert.isTrue(ExcelUtils.pageLimit > 0, "查询数据sql每页条数必须大于0"); + Assert.isTrue(ExcelUtils.maxExportSize > 0, "excel最大导出条数必须大于0"); + } + + /** + * 导出excel数据到HttpServletResponse + * + * @param parameter + * @param data 导出数据 + * @param head 表头 + * @param fileName 文件名 + * @param response HttpServletResponse + * @since 2.3.0 + */ + public static void export(List data, Class head, String fileName, HttpServletResponse response) { + ExcelUtils.export(data, head, fileName, response, DEFAULT_EXCEL_SHEET_SIZE); + } + + /** + * 导出excel数据到HttpServletResponse + * + * @param parameter + * @param data 导出数据 + * @param head 表头 + * @param fileName 文件名 + * @param response HttpServletResponse + * @param rowNumPerSheet 工作表行数 + * @since 2.3.0 + */ + public static void export(List data, Class head, String fileName, HttpServletResponse response, + int rowNumPerSheet) { + try { + ExcelUtils.export(data, head, fileName, response.getOutputStream(), rowNumPerSheet); + ExcelUtils.setHeader(fileName, response); + } catch (IOException e) { + Assert.hasText("导出异常", e.getMessage()); + } + } + + /** + * 导出excel数据到OutputStream + * + * @param parameter + * @param data 导出数据 + * @param head 表头 + * @param sheetName 工作表名 + * @param outputStream OutputStream + * @since 2.3.0 + */ + public static void export(List data, Class head, String sheetName, OutputStream outputStream) { + ExcelUtils.export(data, head, sheetName, outputStream, DEFAULT_EXCEL_SHEET_SIZE); + } + + /** + * 导出excel数据到OutputStream + * + * @param parameter + * @param data 导出数据 + * @param head 表头 + * @param sheetName sheet名 + * @param outputStream OutputStream + * @param rowNumPerSheet 工作表行数 + * @since 2.3.0 + */ + public static void export(List data, Class head, String sheetName, OutputStream outputStream, int rowNumPerSheet) { + Assert.notEmpty(data, "数据为空"); + Assert.notNull(sheetName, "工作表名不能为空"); + Assert.isTrue(rowNumPerSheet > 0, "工作表行数必须大于0"); + ExcelWriter excelWriter = ExcelUtils.createWriteBuilder(head, outputStream).build(); + if (data.size() > rowNumPerSheet) { + List> partitionData = Lists.partition(data, rowNumPerSheet); + for (int i = 0; i < partitionData.size(); i++) { + ExcelUtils.write(excelWriter, partitionData.get(i), sheetName + StringPool.DASH + i); + } + } else { + ExcelUtils.write(excelWriter, data, sheetName); + } + excelWriter.finish(); + } + + /** + * 根据表头和OutputStream创建ExcelWriterBuilder + * + * @param parameter + * @param head 表头 + * @param outputStream OutputStream + * @return ExcelWriterBuilder excel writer builder + * @since 2.3.0 + */ + public static ExcelWriterBuilder createWriteBuilder(Class head, OutputStream outputStream) { + Assert.notNull(head, "表头不能为空"); + Assert.notNull(outputStream, "导出位置不能为空"); + return EasyExcel.write(outputStream, head) + .autoCloseStream(true) + .excelType(ExcelTypeEnum.XLSX) + .registerConverter(new SerializableStringConverter()); + } + + /** + * 创建ExcelWriterSheet + * + * @param sheetName sheet名 + * @return the write sheet + * @since 2.3.0 + */ + public static WriteSheet createWriteSheet(String sheetName) { + return EasyExcel.writerSheet(sheetName).build(); + } + + /** + * 写入sheet + * + * @param parameter + * @param excelWriter ExcelWriter + * @param writeSheet WriteSheet + * @param data sheet数据 + * @since 2.3.0 + */ + public static void write(ExcelWriter excelWriter, WriteSheet writeSheet, List data) { + excelWriter.write(data, writeSheet); + } + + /** + * 写入sheet + * + * @param parameter + * @param excelWriter ExcelWriter + * @param data sheet数据 + * @param sheetName sheet名 + * @since 2.3.0 + */ + public static void write(ExcelWriter excelWriter, List data, String sheetName) { + WriteSheet writeSheet = ExcelUtils.createWriteSheet(sheetName); + excelWriter.write(data, writeSheet); + } + + /** + * 设置Header + * + * @param fileName 文件名 + * @param response HttpServletResponse + * @since 2.3.0 + */ + public static void setHeader(String fileName, HttpServletResponse response) { + response.setContentType(EXCEL_CONTENT_TYPE); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, + "attachment;filename=" + UrlUtils.encodePath(fileName, StringPool.UTF_8) + ".xlsx"); + } + + /** + * 导出excel数据到OutputStream + * + * @param parameter + * @param head 表头 + * @param fileName 文件名 + * @param response HttpServletResponse + * @param supplier DataSupplier + * @since 2.3.0 + */ + @SneakyThrows + public static void stepwiseExport(Class head, String fileName, HttpServletResponse response, DataSupplier supplier) { + ExcelUtils.stepwiseExport(head, fileName, response.getOutputStream(), supplier); + ExcelUtils.setHeader(fileName, response); + } + + /** + * 导出excel数据到OutputStream + * + * @param parameter + * @param head 表头 + * @param sheetName sheet名 + * @param outputStream OutputStream + * @param supplier DataSupplier + * @throws Exception exception + * @since 2.3.0 + */ + public static void stepwiseExport(Class head, String sheetName, OutputStream outputStream, DataSupplier supplier) + throws Exception { + Assert.notNull(supplier, "数据源不能为空"); + Assert.notNull(sheetName, "工作表名不能为空"); + ExcelUtils.checkExportSize(supplier); + // 分页查询数据导出 + // 先查第一页数据 + IPage data = supplier.get(1, ExcelUtils.pageLimit); + Assert.isTrue(data.getTotal() > 0, "导出数据不能为空"); + // 当前页条数 + ExcelWriter excelWriter = ExcelUtils.createWriteBuilder(head, outputStream).build(); + WriteSheet writeSheet = ExcelUtils.createWriteSheet(sheetName); + // 当前页小于等于总页数 + while (data != null && data.getCurrent() <= data.getPages()) { + CompletableFuture> nextPageFuture = null; + if (data.getCurrent() < data.getPages()) { + int nextPage = (int) (data.getCurrent() + 1); + nextPageFuture = CompletableFuture.supplyAsync(() -> supplier.get(nextPage, ExcelUtils.pageLimit)); + } + List records = data.getRecords(); + ExcelUtils.write(excelWriter, writeSheet, records); + // 当前页数达到最大页数停止 + data = nextPageFuture != null ? nextPageFuture.get() : null; + } + excelWriter.finish(); + } + + /** + * 校验导出条数限制 + * + * @param parameter + * @param supplier DataSupplier + * @since 2.3.0 + */ + private static void checkExportSize(DataSupplier supplier) { + if (ExcelUtils.limitExportSize) { + // 开启限制导出条数 + IPage data = supplier.get(1, 1); + Assert.isTrue(data.getTotal() > 0, "导出数据不能为空"); + Assert.isTrue(data.getTotal() <= ExcelUtils.maxExportSize, + "导出数据条数不能超过最大限制:" + ExcelUtils.maxExportSize); + } + } +} diff --git a/src/main/java/com/aos/fileidentify/util/PdfUtils.java b/src/main/java/com/aos/fileidentify/util/PdfUtils.java index 3c86f6b..6bba685 100644 --- a/src/main/java/com/aos/fileidentify/util/PdfUtils.java +++ b/src/main/java/com/aos/fileidentify/util/PdfUtils.java @@ -58,33 +58,60 @@ import java.util.zip.ZipOutputStream; * @since 1.0.0 */ public class PdfUtils { + /** FILE_DIR */ public static final String FILE_DIR = "E:\\guor\\itext\\"; + /** CONST_JPG_JAVA */ public static final String CONST_JPG_JAVA = FILE_DIR + "java.jpg"; + /** CONST_JPG_NGINX */ public static final String CONST_JPG_NGINX = FILE_DIR + "nginx.jpg"; + /** CONST_NEZHA */ private static final String CONST_NEZHA = "哪吒编程"; + /** CONST_NEZHA_PROGRAM */ private static final String CONST_NEZHA_PROGRAM = "获取Java学习资料请关注公众号:哪吒编程"; + /** CONST_BIBIDONG */ private static final String CONST_BIBIDONG = "比比东"; + /** CONST_YUNYUN */ private static final String CONST_YUNYUN = "云韵"; + /** CONST_BAIDU */ private static final String CONST_BAIDU = "百度一下 你就知道"; + /** CONST_BAIDU_URL */ private static final String CONST_BAIDU_URL = "https://www.baidu.com"; + /** CONST_PAGE_FIRST */ private static final String CONST_PAGE_FIRST = "第一页"; + /** CONST_PAGE_SECOND */ private static final String CONST_PAGE_SECOND = "第二页"; + /** CONST_PAGE_THIRD */ private static final String CONST_PAGE_THIRD = "第三页"; + /** CONST_PAGE_FOUR */ private static final String CONST_PAGE_FOUR = "第四页"; + /** CONST_PAGE_FIVE */ private static final String CONST_PAGE_FIVE = "第五页"; + /** CONST_TITLE_FIRST */ private static final String CONST_TITLE_FIRST = "一级标题"; + /** CONST_TITLE_SECOND */ private static final String CONST_TITLE_SECOND = "二级标题"; + /** CONST_CONTENT */ private static final String CONST_CONTENT = "内容"; + /** STATIC_FONT_CHINESE */ // 普通中文字体 public static Font STATIC_FONT_CHINESE = null; + /** STATIC_FONT_LINK */ // 超链字体 public static Font STATIC_FONT_LINK = null; + /** document */ public static Document document; + /** + * Pdf font init + * + * @throws IOException io exception + * @throws DocumentException document exception + * @since 0.0.1 + */ private static void pdfFontInit() throws IOException, DocumentException { // 微软雅黑 BaseFont chinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); @@ -121,6 +148,10 @@ public class PdfUtils { /** * 创建一个 PDF 文件,并添加文本 + * + * @throws IOException io exception + * @throws DocumentException document exception + * @since 0.0.1 */ public static void createPDF() throws IOException, DocumentException { // 实例化 document @@ -145,6 +176,10 @@ public class PdfUtils { /** * 创建PDF文件,修改文件的属性 + * + * @throws FileNotFoundException file not found exception + * @throws DocumentException document exception + * @since 0.0.1 */ public static void createPDFWithColor() throws FileNotFoundException, DocumentException { // 页面大小 @@ -169,6 +204,10 @@ public class PdfUtils { /** * 创建带密码的PDF + * + * @throws FileNotFoundException file not found exception + * @throws DocumentException document exception + * @since 0.0.1 */ public static void createPDFWithPassWord() throws FileNotFoundException, DocumentException { // 页面大小 @@ -188,6 +227,10 @@ public class PdfUtils { /** * 为PDF添加页 + * + * @throws FileNotFoundException file not found exception + * @throws DocumentException document exception + * @since 0.0.1 */ public static void createPDFWithNewPages() throws FileNotFoundException, DocumentException { document = new Document(); @@ -210,6 +253,10 @@ public class PdfUtils { /** * 为PDF文件添加水印,背景图 + * + * @throws IOException io exception + * @throws DocumentException document exception + * @since 0.0.1 */ public static void createPDFWithWaterMark() throws IOException, DocumentException { FileOutputStream out = new FileOutputStream(FILE_DIR + "createPDFWithWaterMark.pdf"); @@ -272,6 +319,10 @@ public class PdfUtils { * Chunk : 块,PDF文档中描述的最小原子元素 * Phrase : 短语,Chunk的集合 * Paragraph : 段落,一个有序的Phrase集合 + * + * @throws DocumentException document exception + * @throws FileNotFoundException file not found exception + * @since 0.0.1 */ public static void createPDFWithContent() throws DocumentException, FileNotFoundException { FileOutputStream out = new FileOutputStream(FILE_DIR + "createPDFWithContent.pdf"); @@ -362,6 +413,11 @@ public class PdfUtils { /** * 插入锚Anchor, Image, 章节Chapter, 子列表Section + * + * @throws DocumentException document exception + * @throws MalformedURLException malformed url exception + * @throws IOException io exception + * @since 0.0.1 */ public static void createPDFWithExtraContent() throws DocumentException, MalformedURLException, IOException { FileOutputStream out = new FileOutputStream(FILE_DIR + "createPDFWithExtraContent.pdf"); @@ -419,6 +475,9 @@ public class PdfUtils { /** * 画图 + * + * @throws Exception exception + * @since 0.0.1 */ public static void draw() throws Exception { FileOutputStream out = new FileOutputStream(FILE_DIR + "draw.pdf"); @@ -473,6 +532,9 @@ public class PdfUtils { /** * 设置段落 + * + * @throws Exception exception + * @since 0.0.1 */ public static void createPDFWithAlignment() throws Exception { FileOutputStream out = new FileOutputStream(FILE_DIR + "createPDFWithAlignment.pdf"); @@ -522,6 +584,9 @@ public class PdfUtils { /** * 删除页 + * + * @throws Exception exception + * @since 0.0.1 */ public static void createPDFToDeletePage() throws Exception { @@ -551,6 +616,9 @@ public class PdfUtils { /** * 插入 page + * + * @throws Exception exception + * @since 0.0.1 */ public static void insertPage() throws Exception { @@ -587,6 +655,9 @@ public class PdfUtils { /** * 分割 page + * + * @throws Exception exception + * @since 0.0.1 */ public static void splitPDF() throws Exception { @@ -637,6 +708,9 @@ public class PdfUtils { /** * 合并 PDF 文件 + * + * @throws Exception exception + * @since 0.0.1 */ public static void mergePDF() throws Exception { @@ -677,6 +751,9 @@ public class PdfUtils { /** * 排序page + * + * @throws Exception exception + * @since 0.0.1 */ public static void sortpage() throws Exception { FileOutputStream out = new FileOutputStream(FILE_DIR + "sortpage.pdf"); @@ -705,6 +782,9 @@ public class PdfUtils { /** * 页眉页脚 + * + * @throws Exception exception + * @since 0.0.1 */ public static void setHeaderFooter() throws Exception { document = new Document(); @@ -770,6 +850,12 @@ public class PdfUtils { document.close(); } + /** + * Add column text + * + * @throws Exception exception + * @since 0.0.1 + */ public static void addColumnText() throws Exception { FileOutputStream out = new FileOutputStream(FILE_DIR + "addColumnText.pdf"); @@ -793,6 +879,9 @@ public class PdfUtils { /** * 文档视图 + * + * @throws Exception exception + * @since 0.0.1 */ public static void setView() throws Exception { FileOutputStream out = new FileOutputStream(FILE_DIR + "setView.pdf"); @@ -829,6 +918,9 @@ public class PdfUtils { /** * 压缩PDF到Zip + * + * @throws Exception exception + * @since 0.0.1 */ public static void pdfToZip() throws Exception { ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(FILE_DIR + "pdfToZip.zip")); @@ -848,6 +940,9 @@ public class PdfUtils { /** * 添加注释 + * + * @throws Exception exception + * @since 0.0.1 */ public static void addAnnotation() throws Exception { FileOutputStream out = new FileOutputStream(FILE_DIR + "addAnnotation.pdf"); diff --git a/src/main/java/com/aos/fileidentify/util/UrlUtils.java b/src/main/java/com/aos/fileidentify/util/UrlUtils.java new file mode 100644 index 0000000..c31acb9 --- /dev/null +++ b/src/main/java/com/aos/fileidentify/util/UrlUtils.java @@ -0,0 +1,168 @@ +package com.aos.fileidentify.util; + +import com.google.common.base.Joiner; +import com.google.common.collect.Maps; + +import com.aos.fileidentify.util.basic.Charsets; +import com.aos.fileidentify.util.basic.StringUtils; +import com.aos.fileidentify.util.pools.StringPool; + +import org.jetbrains.annotations.NotNull; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.util.Map; + +import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:13 + * @since 1.0.0 + */ +@Slf4j +@UtilityClass +public class UrlUtils extends org.springframework.web.util.UriUtils { + + /** + * Build url params by map + * + * @param map map + * @return the string + * @since 1.7.0 + */ + public static String buildUrlParamsByMap(Map map) { + if (map == null) { + return ""; + } + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : map.entrySet()) { + sb.append(entry.getKey()).append(StringPool.EQUALS).append(entry.getValue()).append(StringPool.AMPERSAND); + } + String s = sb.toString(); + if (s.endsWith(StringPool.AMPERSAND)) { + s = StringUtils.subBefore(s, StringPool.AMPERSAND); + } + return s; + } + + /** + * Build map by url params + * + * @param param param + * @return the map + * @since 1.7.0 + */ + public static @NotNull + Map buildMapByUrlParams(String param) { + Map map = Maps.newHashMap(); + if (StringUtils.isBlank(param)) { + return map; + } + if (param.startsWith(StringPool.QUESTION_MARK)) { + param = StringUtils.subAfter(param, StringPool.QUESTION_MARK); + } + String[] params = param.split(StringPool.AMPERSAND); + for (String s : params) { + String[] p = s.split(StringPool.EQUALS); + if (p.length == 2) { + map.put(p[0], p[1]); + } + } + return map; + } + + /** + * url 编码,同js decodeURIComponent + * + * @param source url + * @param charset 字符集 + * @return 编码后的url string + * @since 1.0.0 + */ + @NotNull + public static String encodeUrl(String source, @NotNull Charset charset) { + return UrlUtils.encode(source, charset.name()); + } + + /** + * url 解码 + * + * @param source url + * @param charset 字符集 + * @return 解码url string + * @since 1.0.0 + */ + @NotNull + public static String decodeUrl(String source, @NotNull Charset charset) { + return UrlUtils.decode(source, charset.name()); + } + + /** + * 获取 url 路径 + * + * @param uriStr 路径 + * @return url路径 path + * @since 1.0.0 + */ + public static String getPath(String uriStr) { + URI uri; + + try { + uri = new URI(uriStr); + } catch (URISyntaxException var3) { + throw new RuntimeException(var3); + } + + return uri.getPath(); + } + + /** + * map 转为 url 参数, 默认需要参数编码 + * + * @param source source + * @return the string + * @since 1.0.0 + */ + @NotNull + public static String asUrlParams(@NotNull Map source) { + return asUrlParams(source, true); + } + + /** + * map 转为 url 参数 + * + * @param source source + * @param urlEncoder url encoder + * @return the string + * @since 1.0.0 + */ + @NotNull + public static String asUrlParams(@NotNull Map source, boolean urlEncoder) { + Map tmp = Maps.newHashMap(); + source.forEach((k, v) -> { + if (k != null) { + try { + if (urlEncoder) { + tmp.put(k, URLEncoder.encode(v, Charsets.UTF_8_NAME)); + } else { + tmp.put(k, v); + } + } catch (UnsupportedEncodingException e) { + log.error("url encode error", e); + } + } + }); + return Joiner.on("&").useForNull("").withKeyValueSeparator("=").join(tmp); + } +} + diff --git a/src/main/java/com/aos/fileidentify/util/basic/Charsets.java b/src/main/java/com/aos/fileidentify/util/basic/Charsets.java new file mode 100644 index 0000000..80a7eef --- /dev/null +++ b/src/main/java/com/aos/fileidentify/util/basic/Charsets.java @@ -0,0 +1,50 @@ +package com.aos.fileidentify.util.basic; + +import org.springframework.util.StringUtils; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.charset.UnsupportedCharsetException; + +import lombok.experimental.UtilityClass; + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:16 + * @since 1.0.0 + */ +@UtilityClass +public class Charsets { + + /** 字符集ISO-8859-1 */ + public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1; + /** The constant ISO_8859_1_NAME. */ + public static final String ISO_8859_1_NAME = ISO_8859_1.name(); + /** 字符集GBK */ + public static final Charset GBK = of("GBK"); + /** The constant GBK_NAME. */ + public static final String GBK_NAME = GBK.name(); + /** 字符集utf-8 */ + public static final Charset UTF_8 = StandardCharsets.UTF_8; + /** The constant UTF_8_NAME. */ + public static final String UTF_8_NAME = UTF_8.name(); + + /** + * 转换为Charset对象 + * + * @param charsetName 字符集,为空则返回默认字符集 + * @return Charsets charset + * @throws UnsupportedCharsetException 编码不支持 + * @since 1.0.0 + */ + public static Charset of(String charsetName) throws UnsupportedCharsetException { + return StringUtils.hasText(charsetName) ? Charset.forName(charsetName) : Charset.defaultCharset(); + } + + +} diff --git a/src/main/java/com/aos/fileidentify/util/basic/NumberUtils.java b/src/main/java/com/aos/fileidentify/util/basic/NumberUtils.java new file mode 100644 index 0000000..bb1aebb --- /dev/null +++ b/src/main/java/com/aos/fileidentify/util/basic/NumberUtils.java @@ -0,0 +1,223 @@ +package com.aos.fileidentify.util.basic; + +import com.sun.istack.internal.NotNull; + +import org.jetbrains.annotations.Contract; + +import javax.annotation.Nullable; + +import cn.hutool.core.util.NumberUtil; +import lombok.experimental.UtilityClass; + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:27 + * @since 1.0.0 + */ +@UtilityClass +public class NumberUtils extends org.springframework.util.NumberUtils { + + /** + * All possible chars for representing a number as a String + */ + public static final char[] DIGITS = { + '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z' + }; + + /** + *

Convert a String to an int, returning + * zero if the conversion fails.

+ *

If the string is null, zero is returned.

+ *
+     *   NumberUtil.toInt(null) = 0
+     *   NumberUtil.toInt("")   = 0
+     *   NumberUtil.toInt("1")  = 1
+     * 
+ * + * @param str the string to convert, may be null + * @return the int represented by the string, or zero if conversion fails + * @since 1.0.0 + */ + public static int toInt(String str) { + return toInt(str, -1); + } + + /** + * Is numer boolean + * + * @param str str + * @return the boolean + * @since 1.0.0 + */ + @Contract("null -> false") + public static boolean isNumer(String str) { + return NumberUtil.isNumber(str); + } + + /** + *

Convert a String to an int, returning a + * default value if the conversion fails.

+ *

If the string is null, the default value is returned.

+ *
+     *   NumberUtil.toInt(null, 1) = 1
+     *   NumberUtil.toInt("", 1)   = 1
+     *   NumberUtil.toInt("1", 0)  = 1
+     * 
+ * + * @param str the string to convert, may be null + * @param defaultValue the default value + * @return the int represented by the string, or the default if conversion fails + * @since 1.0.0 + */ + @Contract("null, _ -> param2") + public static int toInt(@Nullable String str, int defaultValue) { + if (str == null) { + return defaultValue; + } + try { + return Integer.parseInt(str); + } catch (NumberFormatException nfe) { + return defaultValue; + } + } + + /** + *

Convert a String to a long, returning + * zero if the conversion fails.

+ *

If the string is null, zero is returned.

+ *
+     *   NumberUtil.toLong(null) = 0L
+     *   NumberUtil.toLong("")   = 0L
+     *   NumberUtil.toLong("1")  = 1L
+     * 
+ * + * @param str the string to convert, may be null + * @return the long represented by the string, or 0 if conversion fails + * @since 1.0.0 + */ + public static long toLong(String str) { + return toLong(str, 0L); + } + + /** + *

Convert a String to a long, returning a + * default value if the conversion fails.

+ *

If the string is null, the default value is returned.

+ *
+     *   NumberUtil.toLong(null, 1L) = 1L
+     *   NumberUtil.toLong("", 1L)   = 1L
+     *   NumberUtil.toLong("1", 0L)  = 1L
+     * 
+ * + * @param str the string to convert, may be null + * @param defaultValue the default value + * @return the long represented by the string, or the default if conversion fails + * @since 1.0.0 + */ + @Contract("null, _ -> param2") + public static long toLong(@Nullable String str, long defaultValue) { + if (str == null) { + return defaultValue; + } + try { + return Long.parseLong(str); + } catch (NumberFormatException nfe) { + return defaultValue; + } + } + + /** + *

Convert a String to a Double + * + * @param value value + * @return double value + * @since 1.0.0 + */ + @Contract("!null -> !null") + public static Double toDouble(String value) { + return toDouble(value, null); + } + + /** + *

Convert a String to a Double + * + * @param value value + * @param defaultValue 默认值 + * @return double value + * @since 1.0.0 + */ + @Contract("!null, _ -> !null; null, _ -> param2") + public static Double toDouble(@Nullable String value, Double defaultValue) { + if (value != null) { + return Double.valueOf(value.trim()); + } + return defaultValue; + } + + /** + *

Convert a String to a Double + * + * @param value value + * @return double value + * @since 1.0.0 + */ + @Contract("!null -> !null") + public static Float toFloat(String value) { + return toFloat(value, null); + } + + /** + *

Convert a String to a Double + * + * @param value value + * @param defaultValue 默认值 + * @return double value + * @since 1.0.0 + */ + @Contract("!null, _ -> !null; null, _ -> param2") + public static Float toFloat(@Nullable String value, Float defaultValue) { + if (value != null) { + return Float.valueOf(value.trim()); + } + return defaultValue; + } + + /** + * 将 long 转短字符串 为 62 进制 + * + * @param i 数字 + * @return 短字符串 string + * @since 1.0.0 + */ + @NotNull + @Contract(value = "_ -> new", pure = true) + public static String to62String(long i) { + int radix = DIGITS.length; + char[] buf = new char[65]; + int charPos = 64; + i = -i; + while (i <= -radix) { + buf[charPos--] = DIGITS[(int) (-(i % radix))]; + i = i / radix; + } + buf[charPos] = DIGITS[(int) (-i)]; + + return new String(buf, charPos, (65 - charPos)); + } + +} diff --git a/src/main/java/com/aos/fileidentify/util/basic/StringUtils.java b/src/main/java/com/aos/fileidentify/util/basic/StringUtils.java new file mode 100644 index 0000000..9befe06 --- /dev/null +++ b/src/main/java/com/aos/fileidentify/util/basic/StringUtils.java @@ -0,0 +1,1626 @@ +package com.aos.fileidentify.util.basic; + +import com.aos.fileidentify.util.pools.CharPool; +import com.aos.fileidentify.util.pools.StringPool; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.springframework.util.ObjectUtils; +import org.springframework.web.util.HtmlUtils; + +import java.io.StringReader; +import java.io.StringWriter; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +import cn.hutool.core.text.StrSplitter; + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:24 + * @since 1.0.0 + */ +public abstract class StringUtils extends org.springframework.util.StringUtils { + /** INDEX_NOT_FOUND */ + public static final int INDEX_NOT_FOUND = -1; + /** 特殊字符正则,sql特殊字符和空白符 */ + public static final Pattern SPECIAL_CHARS_REGEX = Pattern.compile("[`'\"|/,;()-+*%#·•� \\s]"); + /** BLANK_SYMBOL */ + public static final String BLANK_SYMBOL = "\\s*|\t|\r|\n"; + /** 随机字符串因子 */ + public static final String INT_STR = "0123456789"; + /** STR_STR */ + public static final String STR_STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + /** ALL_STR */ + public static final String ALL_STR = INT_STR + STR_STR; + + /** + * 有 任意 一个 Blank + * + * @param css CharSequence + * @return boolean boolean + * @since 1.0.0 + */ + public static boolean isAnyBlank(CharSequence... css) { + if (ObjectUtils.isEmpty(css)) { + return true; + } + return Stream.of(css).anyMatch(StringUtils::isBlank); + } + + /** + * Check whether the given {@code CharSequence} contains actual text. + *

More specifically, this method returns {@code true} if the + * {@code CharSequence} is not {@code null}, its length is greater than + * 0, and it contains at least one non-whitespace character. + *

+     * StringUtil.isBlank(null) = true
+     * StringUtil.isBlank("") = true
+     * StringUtil.isBlank(" ") = true
+     * StringUtil.isBlank("12345") = false
+     * StringUtil.isBlank(" 12345 ") = false
+     * 
+ * + * @param cs the {@code CharSequence} to check (may be {@code null}) + * @return {@code true} if the {@code CharSequence} is not {@code null}, its length is greater than 0, and it does not contain + * whitespace only + * @see Character#isWhitespace + * @since 1.0.0 + */ + @Contract("null -> true") + public static boolean isBlank(CharSequence cs) { + return !StringUtils.hasText(cs); + } + + /** + * 是否全部都不是 blank + * + * @param css CharSequence + * @return boolean boolean + * @since 1.0.0 + */ + public static boolean isNoneBlank(CharSequence... css) { + if (ObjectUtils.isEmpty(css)) { + return false; + } + return Stream.of(css).allMatch(StringUtils::isNotBlank); + } + + /** + * 是否全部都是 blank + * + * @param css css + * @return the boolean + * @since 1.0.0 + */ + public static boolean isAllBlank(CharSequence... css) { + if (ObjectUtils.isEmpty(css)) { + return true; + } + return Stream.of(css).allMatch(StringUtils::isBlank); + } + + /** + *

Checks if a CharSequence is not empty (""), not null and not whitespace only.

+ *
+     * StringUtil.isNotBlank(null)      = false
+     * StringUtil.isNotBlank("")        = false
+     * StringUtil.isNotBlank(" ")       = false
+     * StringUtil.isNotBlank("bob")     = true
+     * StringUtil.isNotBlank("  bob  ") = true
+     * 
+ * + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is not empty and not null and not whitespace + * @see Character#isWhitespace + * @since 1.0.0 + */ + @Contract("null -> false") + public static boolean isNotBlank(CharSequence cs) { + return StringUtils.hasText(cs); + } + + /** + * 判断一个字符串是否是数字 + * + * @param cs the CharSequence to check, may be null + * @return {boolean} + * @since 1.0.0 + */ + public static boolean isNumeric(CharSequence cs) { + if (isBlank(cs)) { + return false; + } + for (int i = cs.length(); --i >= 0; ) { + int chr = cs.charAt(i); + if (chr < 48 || chr > 57) { + return false; + } + } + return true; + } + + /** + * Convert a {@code Collection} into a delimited {@code String} (e.g., CSV). + *

Useful for {@code toString()} implementations. + * + * @param coll the {@code Collection} to convert + * @return the delimited {@code String} + * @since 1.0.0 + */ + @NotNull + public static String join(Collection coll) { + return StringUtils.collectionToCommaDelimitedString(coll); + } + + /** + * Convert a {@code Collection} into a delimited {@code String} (e.g. CSV). + *

Useful for {@code toString()} implementations. + * + * @param coll the {@code Collection} to convert + * @param delim the delimiter to use (typically a ",") + * @return the delimited {@code String} + * @since 1.0.0 + */ + @NotNull + public static String join(Collection coll, String delim) { + return StringUtils.collectionToDelimitedString(coll, delim); + } + + /** + * Convert a {@code String} array into a comma delimited {@code String} + * (i.e., CSV). + *

Useful for {@code toString()} implementations. + * + * @param arr the array to display + * @return the delimited {@code String} + * @since 1.0.0 + */ + @NotNull + @Contract(pure = true) + public static String join(Object[] arr) { + return StringUtils.arrayToCommaDelimitedString(arr); + } + + /** + * Convert a {@code String} array into a delimited {@code String} (e.g. CSV). + *

Useful for {@code toString()} implementations. + * + * @param arr the array to display + * @param delim the delimiter to use (typically a ",") + * @return the delimited {@code String} + * @since 1.0.0 + */ + @NotNull + @Contract(pure = true) + public static String join(Object[] arr, String delim) { + return StringUtils.arrayToDelimitedString(arr, delim); + } + + /** + * 生成uuid + * + * @return UUID string + * @since 1.0.0 + */ + @NotNull + public static String randomUid() { + ThreadLocalRandom random = ThreadLocalRandom.current(); + return new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY); + } + + /** + * 转义HTML用于安全过滤 + * + * @param html html + * @return {String} + * @since 1.0.0 + */ + @NotNull + public static String escapeHtml(String html) { + return HtmlUtils.htmlEscape(html); + } + + /** + * 清理字符串,清理出某些不可见字符 + * + * @param txt 字符串 + * @return {String} + * @since 1.0.0 + */ + @NotNull + @Contract(pure = true) + public static String cleanChars(@NotNull String txt) { + return txt.replaceAll("[  `·•�\\f\\t\\v\\s]", ""); + } + + + /** + * 有序的格式化文本,使用{number}做为占位符
+ * 例:
+ * 通常使用: format("this is {0} for {1}", "a", "b") =》 this is a for b
+ * + * @param pattern 文本格式 + * @param arguments 参数 + * @return 格式化后的文本 string + * @since 1.0.0 + */ + @NotNull + public static String indexedFormat(@NotNull CharSequence pattern, Object... arguments) { + return MessageFormat.format(pattern.toString(), arguments); + } + + /** + * 切分字符串,不去除切分后每个元素两边的空白符,不去除空白项 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @return 切分后的集合 list + * @since 1.0.0 + */ + @Contract("null, _, _ -> new") + public static List split(CharSequence str, char separator, int limit) { + return split(str, separator, limit, false, false); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 list + * @since 3.0.8 + */ + @Contract("null, _, _, _, _ -> new") + public static List split(CharSequence str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { + if (null == str) { + return new ArrayList<>(0); + } + return StrSplitter.split(str.toString(), separator, limit, isTrim, ignoreEmpty); + } + + /** + * 切分字符串,去除切分后每个元素两边的空白符,去除空白项 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @return 切分后的集合 list + * @since 3.1.2 + */ + @Contract("null, _ -> new") + public static List splitTrim(CharSequence str, char separator) { + return splitTrim(str, separator, -1); + } + + /** + * 切分字符串,去除切分后每个元素两边的空白符,去除空白项 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @return 切分后的集合 list + * @since 3.1.0 + */ + @Contract("null, _, _ -> new") + private static List splitTrim(CharSequence str, char separator, int limit) { + return split(str, separator, limit, true, true); + } + + /** + * 切分字符串,去除切分后每个元素两边的空白符,去除空白项 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @return 切分后的集合 list + * @since 3.2.0 + */ + @Contract("null, _ -> new") + public static List splitTrim(CharSequence str, CharSequence separator) { + return splitTrim(str, separator, -1); + } + + /** + * 切分字符串,去除切分后每个元素两边的空白符,去除空白项 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @return 切分后的集合 list + * @since 3.2.0 + */ + @Contract("null, _, _ -> new") + private static List splitTrim(CharSequence str, CharSequence separator, int limit) { + return split(str, separator, limit, true, true); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 list + * @since 3.2.0 + */ + @Contract("null, _, _, _, _ -> new") + public static List split(CharSequence str, CharSequence separator, int limit, boolean isTrim, boolean ignoreEmpty) { + if (null == str) { + return new ArrayList<>(0); + } + String separatorStr = (null == separator) ? null : separator.toString(); + return StrSplitter.split(str.toString(), separatorStr, limit, isTrim, ignoreEmpty); + } + + /** + * 切分字符串,不限制分片数量 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 list + * @since 3.0.8 + */ + @Contract("null, _, _, _ -> new") + public static List split(CharSequence str, char separator, boolean isTrim, boolean ignoreEmpty) { + return split(str, separator, 0, isTrim, ignoreEmpty); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符 + * @return 字符串 string [ ] + * @since 1.0.0 + */ + @NotNull + @Contract("null, _ -> new") + public static String[] split(CharSequence str, CharSequence separator) { + if (str == null) { + return new String[0]; + } + + String separatorStr = (null == separator) ? null : separator.toString(); + return StrSplitter.splitToArray(str.toString(), separatorStr, 0, false, false); + } + + /** + * 根据给定长度,将给定字符串截取为多个部分 + * + * @param str 字符串 + * @param len 每一个小节的长度 + * @return 截取后的字符串数组 string [ ] + * @since 1.0.0 + */ + @Contract("null, _ -> new") + public static String[] split(CharSequence str, int len) { + if (null == str) { + return new String[0]; + } + return StrSplitter.splitByLength(str.toString(), len); + } + + /** + * 指定字符是否在字符串中出现过 + * + * @param str 字符串 + * @param searchChar 被查找的字符 + * @return 是否包含 boolean + * @since 3.1.2 + */ + public static boolean contains(CharSequence str, char searchChar) { + return indexOf(str, searchChar) > -1; + } + + /** + * 指定范围内查找指定字符 + * + * @param str 字符串 + * @param searchChar 被查找的字符 + * @return 位置 int + * @since 1.0.0 + */ + public static int indexOf(CharSequence str, char searchChar) { + return indexOf(str, searchChar, 0); + } + + /** + * 指定范围内查找指定字符 + * + * @param str 字符串 + * @param searchChar 被查找的字符 + * @param start 起始位置,如果小于0,从0开始查找 + * @return 位置 int + * @since 1.0.0 + */ + public static int indexOf(CharSequence str, char searchChar, int start) { + if (str instanceof String) { + return ((String) str).indexOf(searchChar, start); + } else { + return indexOf(str, searchChar, start, -1); + } + } + + /** + * 指定范围内查找指定字符 + * + * @param str 字符串 + * @param searchChar 被查找的字符 + * @param start 起始位置,如果小于0,从0开始查找 + * @param end 终止位置,如果超过str.length()则默认查找到字符串末尾 + * @return 位置 int + * @since 1.0.0 + */ + public static int indexOf(@NotNull CharSequence str, char searchChar, int start, int end) { + int len = str.length(); + if (start < 0 || start > len) { + start = 0; + } + if (end > len || end < 0) { + end = len; + } + for (int i = start; i < end; i++) { + if (str.charAt(i) == searchChar) { + return i; + } + } + return -1; + } + + /** + * 截取分隔字符串之前的字符串,不包括分隔字符串
+ * 如果给定的字符串为空串 (null或"") 或者分隔字符串为null,返回原字符串
+ * 如果分隔字符串为空串"",则返回空串,如果分隔字符串未找到,返回原字符串 + *

+ * 栗子: + *

+     * StringUtil.subBefore(null, *)      = null
+     * StringUtil.subBefore("", *)        = ""
+     * StringUtil.subBefore("abc", "a")   = ""
+     * StringUtil.subBefore("abcba", "b") = "a"
+     * StringUtil.subBefore("abc", "c")   = "ab"
+     * StringUtil.subBefore("abc", "d")   = "abc"
+     * StringUtil.subBefore("abc", "")    = ""
+     * StringUtil.subBefore("abc", null)  = "abc"
+     * 
+ * + * @param string 被查找的字符串 + * @param separator 分隔字符串 (不包括) + * @param isLastSeparator 是否查找最后一个分隔字符串 (多次出现分隔字符串时选取最后一个) ,true为选取最后一个 + * @return 切割后的字符串 string + * @since 3.1.1 + */ + @Nullable + public static String subBefore(CharSequence string, CharSequence separator, boolean isLastSeparator) { + if (StringUtils.isEmpty(string) || separator == null) { + return null == string ? null : string.toString(); + } + + String str = string.toString(); + String sep = separator.toString(); + if (sep.isEmpty()) { + return StringPool.EMPTY; + } + int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep); + if (pos == INDEX_NOT_FOUND) { + return str; + } + return str.substring(0, pos); + } + + /** + * 默认查找最后一个分隔符 + * + * @param string string + * @param separator separator + * @return the string + * @since 1.0.0 + */ + public static String subBefore(CharSequence string, CharSequence separator) { + return subBefore(string, separator, true); + } + + /** + * 截取分隔字符串之后的字符串,不包括分隔字符串
+ * 如果给定的字符串为空串 (null或"") ,返回原字符串
+ * 如果分隔字符串为空串 (null或"") ,则返回空串,如果分隔字符串未找到,返回空串 + *

+ * 栗子: + *

+     * StringUtil.subAfter(null, *)      = null
+     * StringUtil.subAfter("", *)        = ""
+     * StringUtil.subAfter(*, null)      = ""
+     * StringUtil.subAfter("abc", "a")   = "bc"
+     * StringUtil.subAfter("abcba", "b") = "cba"
+     * StringUtil.subAfter("abc", "c")   = ""
+     * StringUtil.subAfter("abc", "d")   = ""
+     * StringUtil.subAfter("abc", "")    = "abc"
+     * 
+ * + * @param string 被查找的字符串 + * @param separator 分隔字符串 (不包括) + * @param isLastSeparator 是否查找最后一个分隔字符串 (多次出现分隔字符串时选取最后一个) ,true为选取最后一个 + * @return 切割后的字符串 string + * @since 3.1.1 + */ + @Nullable + public static String subAfter(CharSequence string, CharSequence separator, boolean isLastSeparator) { + if (StringUtils.isEmpty(string)) { + return null == string ? null : string.toString(); + } + if (separator == null) { + return StringPool.EMPTY; + } + String str = string.toString(); + String sep = separator.toString(); + int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep); + if (pos == INDEX_NOT_FOUND) { + return StringPool.EMPTY; + } + return str.substring(pos + separator.length()); + } + + /** + * 默认查找第一个分隔符 + * + * @param string string + * @param separator separator + * @return the string + * @since 1.0.0 + */ + public static String subAfter(CharSequence string, CharSequence separator) { + return subAfter(string, separator, false); + } + + /** + * 截取指定字符串中间部分,不包括标识字符串
+ *

+ * 栗子: + *

+     * StringUtil.subBetween(null, *)            = null
+     * StringUtil.subBetween("", "")             = ""
+     * StringUtil.subBetween("", "tag")          = null
+     * StringUtil.subBetween("tagabctag", null)  = null
+     * StringUtil.subBetween("tagabctag", "")    = ""
+     * StringUtil.subBetween("tagabctag", "tag") = "abc"
+     * 
+ * + * @param str 被切割的字符串 + * @param beforeAndAfter 截取开始和结束的字符串标识 + * @return 截取后的字符串 string + * @since 3.1.1 + */ + @Contract("null, _ -> null; !null, null -> null") + public static String subBetween(CharSequence str, CharSequence beforeAndAfter) { + return subBetween(str, beforeAndAfter, beforeAndAfter); + } + + /** + * 截取指定字符串中间部分,不包括标识字符串
+ *

+ * 栗子: + *

+     * StringUtil.subBetween("wx[b]yz", "[", "]") = "b"
+     * StringUtil.subBetween(null, *, *)          = null
+     * StringUtil.subBetween(*, null, *)          = null
+     * StringUtil.subBetween(*, *, null)          = null
+     * StringUtil.subBetween("", "", "")          = ""
+     * StringUtil.subBetween("", "", "]")         = null
+     * StringUtil.subBetween("", "[", "]")        = null
+     * StringUtil.subBetween("yabcz", "", "")     = ""
+     * StringUtil.subBetween("yabcz", "y", "z")   = "abc"
+     * StringUtil.subBetween("yabczyabcz", "y", "z")   = "abc"
+     * 
+ * + * @param str 被切割的字符串 + * @param before 截取开始的字符串标识 + * @param after 截取到的字符串标识 + * @return 截取后的字符串 string + * @since 3.1.1 + */ + @Contract("null, _, _ -> null; !null, null, _ -> null; !null, !null, null -> null") + private static String subBetween(CharSequence str, CharSequence before, CharSequence after) { + if (str == null || before == null || after == null) { + return null; + } + + String str2 = str.toString(); + String before2 = before.toString(); + String after2 = after.toString(); + + int start = str2.indexOf(before2); + if (start != INDEX_NOT_FOUND) { + int end = str2.indexOf(after2, start + before2.length()); + if (end != INDEX_NOT_FOUND) { + return str2.substring(start + before2.length(), end); + } + } + return null; + } + + /** + * 去掉指定前缀 + * + * @param str 字符串 + * @param prefix 前缀 + * @return 切掉后的字符串 ,若前缀不是 preffix, 返回原字符串 + * @since 1.0.0 + */ + public static String removePrefix(CharSequence str, CharSequence prefix) { + if (StringUtils.isEmpty(str) || StringUtils.isEmpty(prefix)) { + return StringPool.EMPTY; + } + + String str2 = str.toString(); + if (str2.startsWith(prefix.toString())) { + return subSuf(str2, prefix.length()); + } + return str2; + } + + /** + * 切割指定位置之后部分的字符串 + * + * @param string 字符串 + * @param fromIndex 切割开始的位置 (包括) + * @return 切割后后剩余的后半部分字符串 string + * @since 1.0.0 + */ + @Nullable + public static String subSuf(CharSequence string, int fromIndex) { + if (StringUtils.isEmpty(string)) { + return StringPool.EMPTY; + } + return sub(string, fromIndex, string.length()); + } + + /** + * 改进JDK subString
+ * index从0开始计算,最后一个字符为-1
+ * 如果from和to位置一样,返回 ""
+ * 如果from或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length
+ * 如果经过修正的index中from大于to,则互换from和to example:
+ * abcdefgh 2 3 =》 c
+ * abcdefgh 2 -3 =》 cde
+ * + * @param str String + * @param fromIndex 开始的index (包括) + * @param toIndex 结束的index (不包括) + * @return 字串 string + * @since 1.0.0 + */ + public static String sub(CharSequence str, int fromIndex, int toIndex) { + if (StringUtils.isEmpty(str)) { + return StringPool.EMPTY; + } + int len = str.length(); + + if (fromIndex < 0) { + fromIndex = len + fromIndex; + if (fromIndex < 0) { + fromIndex = 0; + } + } else if (fromIndex > len) { + fromIndex = len; + } + + if (toIndex < 0) { + toIndex = len + toIndex; + if (toIndex < 0) { + toIndex = len; + } + } else if (toIndex > len) { + toIndex = len; + } + + if (toIndex < fromIndex) { + int tmp = fromIndex; + fromIndex = toIndex; + toIndex = tmp; + } + + if (fromIndex == toIndex) { + return StringPool.EMPTY; + } + + return str.toString().substring(fromIndex, toIndex); + } + + /** + * 忽略大小写去掉指定前缀 + * + * @param str 字符串 + * @param prefix 前缀 + * @return 切掉后的字符串 ,若前缀不是 prefix, 返回原字符串 + * @since 1.0.0 + */ + public static String removePrefixIgnoreCase(CharSequence str, CharSequence prefix) { + if (StringUtils.isEmpty(str) || StringUtils.isEmpty(prefix)) { + return StringPool.EMPTY; + } + + String str2 = str.toString(); + if (str2.toLowerCase().startsWith(prefix.toString().toLowerCase())) { + return subSuf(str2, prefix.length()); + } + return str2; + } + + /** + * 去掉指定后缀,并小写首字母 + * + * @param str 字符串 + * @param suffix 后缀 + * @return 切掉后的字符串 ,若后缀不是 suffix, 返回原字符串 + * @since 1.0.0 + */ + @NotNull + public static String removeSufAndLowerFirst(CharSequence str, CharSequence suffix) { + return firstCharToLower(removeSuffix(str, suffix)); + } + + /** + * 首字母变小写 + * + * @param str 字符串 + * @return {String} + * @since 1.0.0 + */ + @NotNull + public static String firstCharToLower(@NotNull String str) { + char firstChar = str.charAt(0); + if (firstChar >= CharPool.UPPER_A && firstChar <= CharPool.UPPER_Z) { + char[] arr = str.toCharArray(); + arr[0] += (CharPool.LOWER_A - CharPool.UPPER_A); + return new String(arr); + } + return str; + } + + /** + * 去掉指定后缀 + * + * @param str 字符串 + * @param suffix 后缀 + * @return 切掉后的字符串 ,若后缀不是 suffix, 返回原字符串 + * @since 1.0.0 + */ + public static String removeSuffix(CharSequence str, CharSequence suffix) { + if (StringUtils.isEmpty(str) || StringUtils.isEmpty(suffix)) { + return StringPool.EMPTY; + } + + String str2 = str.toString(); + if (str2.endsWith(suffix.toString())) { + return subPre(str2, str2.length() - suffix.length()); + } + return str2; + } + + /** + * 切割指定位置之前部分的字符串 + * + * @param string 字符串 + * @param toIndex 切割到的位置 (不包括) + * @return 切割后的剩余的前半部分字符串 string + * @since 1.0.0 + */ + private static String subPre(CharSequence string, int toIndex) { + return sub(string, 0, toIndex); + } + + /** + * 忽略大小写去掉指定后缀 + * + * @param str 字符串 + * @param suffix 后缀 + * @return 切掉后的字符串 ,若后缀不是 suffix, 返回原字符串 + * @since 1.0.0 + */ + public static String removeSuffixIgnoreCase(CharSequence str, CharSequence suffix) { + if (StringUtils.isEmpty(str) || StringUtils.isEmpty(suffix)) { + return StringPool.EMPTY; + } + + String str2 = str.toString(); + if (str2.toLowerCase().endsWith(suffix.toString().toLowerCase())) { + return subPre(str2, str2.length() - suffix.length()); + } + return str2; + } + + /** + * 首字母变大写 + * + * @param str 字符串 + * @return {String} + * @since 1.0.0 + */ + public static String firstCharToUpper(String str) { + if (isBlank(str)) { + return str; + } + char firstChar = str.charAt(0); + if (firstChar >= CharPool.LOWER_A && firstChar <= CharPool.LOWER_Z) { + char[] arr = str.toCharArray(); + arr[0] -= (CharPool.LOWER_A - CharPool.UPPER_A); + return new String(arr); + } + return str; + } + + /** + * 指定范围内查找字符串,忽略大小写
+ *
+     * StringUtil.indexOfIgnoreCase(null, *, *)          = -1
+     * StringUtil.indexOfIgnoreCase(*, null, *)          = -1
+     * StringUtil.indexOfIgnoreCase("", "", 0)           = 0
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
+     * StringUtil.indexOfIgnoreCase("abc", "", 9)        = -1
+     * 
+ * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @return 位置 int + * @since 3.2.1 + */ + public static int indexOfIgnoreCase(CharSequence str, CharSequence searchStr) { + return indexOfIgnoreCase(str, searchStr, 0); + } + + /** + * 指定范围内查找字符串 + *
+     * StringUtil.indexOfIgnoreCase(null, *, *)          = -1
+     * StringUtil.indexOfIgnoreCase(*, null, *)          = -1
+     * StringUtil.indexOfIgnoreCase("", "", 0)           = 0
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
+     * StringUtil.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
+     * StringUtil.indexOfIgnoreCase("abc", "", 9)        = -1
+     * 
+ * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @param fromIndex 起始位置 + * @return 位置 int + * @since 3.2.1 + */ + private static int indexOfIgnoreCase(CharSequence str, CharSequence searchStr, int fromIndex) { + return indexOf(str, searchStr, fromIndex, true); + } + + /** + * 指定范围内反向查找字符串 + * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @param fromIndex 起始位置 + * @param ignoreCase 是否忽略大小写 + * @return 位置 int + * @since 3.2.1 + */ + public static int indexOf(CharSequence str, CharSequence searchStr, int fromIndex, boolean ignoreCase) { + if (str == null || searchStr == null) { + return INDEX_NOT_FOUND; + } + if (fromIndex < 0) { + fromIndex = 0; + } + + int endLimit = str.length() - searchStr.length() + 1; + if (fromIndex > endLimit) { + return INDEX_NOT_FOUND; + } + if (searchStr.length() == 0) { + return fromIndex; + } + + if (!ignoreCase) { + // 不忽略大小写调用JDK方法 + return str.toString().indexOf(searchStr.toString(), fromIndex); + } + + for (int i = fromIndex; i < endLimit; i++) { + if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) { + return i; + } + } + return INDEX_NOT_FOUND; + } + + /** + * 截取两个字符串的不同部分 (长度一致) ,判断截取的子串是否相同
+ * 任意一个字符串为null返回false + * + * @param str1 第一个字符串 + * @param start1 第一个字符串开始的位置 + * @param str2 第二个字符串 + * @param start2 第二个字符串开始的位置 + * @param length 截取长度 + * @param ignoreCase 是否忽略大小写 + * @return 子串是否相同 boolean + * @since 3.2.1 + */ + @SuppressWarnings("checkstyle:ParameterNumber") + @Contract("null, _, _, _, _, _ -> false; !null, _, null, _, _, _ -> false") + private static boolean isSubEquals(CharSequence str1, + int start1, + CharSequence str2, + int start2, + int length, + boolean ignoreCase) { + if (null == str1 || null == str2) { + return false; + } + + return str1.toString().regionMatches(ignoreCase, start1, str2.toString(), start2, length); + } + + /** + * 指定范围内查找字符串,忽略大小写
+ * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @return 位置 int + * @since 3.2.1 + */ + public static int lastIndexOfIgnoreCase(CharSequence str, CharSequence searchStr) { + return lastIndexOfIgnoreCase(str, searchStr, str.length()); + } + + /** + * 指定范围内查找字符串,忽略大小写
+ * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @param fromIndex 起始位置,从后往前计数 + * @return 位置 int + * @since 3.2.1 + */ + private static int lastIndexOfIgnoreCase(CharSequence str, CharSequence searchStr, int fromIndex) { + return lastIndexOf(str, searchStr, fromIndex, true); + } + + /** + * 指定范围内查找字符串
+ * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @param fromIndex 起始位置,从后往前计数 + * @param ignoreCase 是否忽略大小写 + * @return 位置 int + * @since 3.2.1 + */ + private static int lastIndexOf(CharSequence str, CharSequence searchStr, int fromIndex, boolean ignoreCase) { + if (str == null || searchStr == null) { + return INDEX_NOT_FOUND; + } + if (fromIndex < 0) { + fromIndex = 0; + } + fromIndex = Math.min(fromIndex, str.length()); + + if (searchStr.length() == 0) { + return fromIndex; + } + + if (!ignoreCase) { + // 不忽略大小写调用JDK方法 + return str.toString().lastIndexOf(searchStr.toString(), fromIndex); + } + + for (int i = fromIndex; i > 0; i--) { + if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) { + return i; + } + } + return INDEX_NOT_FOUND; + } + + /** + * 返回字符串 searchStr 在字符串 str 中第 ordinal 次出现的位置.
+ * 此方法来自: Apache-Commons-Lang + *

+ * 栗子 (*代表任意字符) : + *

+     * StringUtil.ordinalIndexOf(null, *, *)          = -1
+     * StringUtil.ordinalIndexOf(*, null, *)          = -1
+     * StringUtil.ordinalIndexOf("", "", *)           = 0
+     * StringUtil.ordinalIndexOf("aabaabaa", "a", 1)  = 0
+     * StringUtil.ordinalIndexOf("aabaabaa", "a", 2)  = 1
+     * StringUtil.ordinalIndexOf("aabaabaa", "b", 1)  = 2
+     * StringUtil.ordinalIndexOf("aabaabaa", "b", 2)  = 5
+     * StringUtil.ordinalIndexOf("aabaabaa", "ab", 1) = 1
+     * StringUtil.ordinalIndexOf("aabaabaa", "ab", 2) = 4
+     * StringUtil.ordinalIndexOf("aabaabaa", "", 1)   = 0
+     * StringUtil.ordinalIndexOf("aabaabaa", "", 2)   = 0
+     * 
+ * + * @param str 被检查的字符串,可以为null + * @param searchStr 被查找的字符串,可以为null + * @param ordinal 第几次出现的位置 + * @return 查找到的位置 int + * @since 3.2.3 + */ + public static int ordinalIndexOf(String str, String searchStr, int ordinal) { + if (str == null || searchStr == null || ordinal <= 0) { + return INDEX_NOT_FOUND; + } + if (searchStr.length() == 0) { + return 0; + } + int found = 0; + int index = INDEX_NOT_FOUND; + do { + index = str.indexOf(searchStr, index + 1); + if (index < 0) { + return index; + } + found++; + } while (found < ordinal); + return index; + } + + /** + * 比较两个字符串 (大小写敏感) . + *
+     * equalsIgnoreCase(null, null)   = true
+     * equalsIgnoreCase(null, "abc")  = false
+     * equalsIgnoreCase("abc", null)  = false
+     * equalsIgnoreCase("abc", "abc") = true
+     * equalsIgnoreCase("abc", "ABC") = true
+     * 
+ * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * @return 如果两个字符串相同 ,或者都是null,则返回true + * @since 1.0.0 + */ + @Contract("null, null -> true; null, !null -> false; !null, null -> false") + public static boolean equals(CharSequence str1, CharSequence str2) { + return equals(str1, str2, false); + } + + /** + * 比较两个字符串是否相等. + * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * @param ignoreCase 是否忽略大小写 + * @return 如果两个字符串相同 ,或者都是null,则返回true + * @since 3.2.0 + */ + @Contract("null, null, _ -> true; null, !null, _ -> false; !null, null, _ -> false") + public static boolean equals(CharSequence str1, CharSequence str2, boolean ignoreCase) { + if (null == str1) { + // 只有两个都为null才判断相等 + return str2 == null; + } + if (null == str2) { + // 字符串2空,字符串1非空,直接false + return false; + } + + if (ignoreCase) { + return str1.toString().equalsIgnoreCase(str2.toString()); + } else { + return str1.equals(str2); + } + } + + /** + * 比较两个字符串 (大小写不敏感) . + *
+     * equalsIgnoreCase(null, null)   = true
+     * equalsIgnoreCase(null, "abc")  = false
+     * equalsIgnoreCase("abc", null)  = false
+     * equalsIgnoreCase("abc", "abc") = true
+     * equalsIgnoreCase("abc", "ABC") = true
+     * 
+ * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * @return 如果两个字符串相同 ,或者都是null,则返回true + * @since 1.0.0 + */ + @Contract("null, null -> true; null, !null -> false; !null, null -> false") + public static boolean equalsIgnoreCase(CharSequence str1, CharSequence str2) { + return equals(str1, str2, true); + } + + /** + * 创建StringBuilder对象 + * + * @return StringBuilder对象 string builder + * @since 1.0.0 + */ + @NotNull + @Contract(value = " -> new", pure = true) + public static StringBuilder builder() { + return new StringBuilder(); + } + + /** + * 创建StringBuilder对象 + * + * @param capacity 初始大小 + * @return StringBuilder对象 string builder + * @since 1.0.0 + */ + @NotNull + @Contract(value = "_ -> new", pure = true) + public static StringBuilder builder(int capacity) { + return new StringBuilder(capacity); + } + + /** + * 创建StringBuilder对象 + * + * @param strs 初始字符串列表 + * @return StringBuilder对象 string builder + * @since 1.0.0 + */ + public static StringBuilder builder(@NotNull CharSequence... strs) { + StringBuilder sb = new StringBuilder(); + for (CharSequence str : strs) { + sb.append(str); + } + return sb; + } + + /** + * 创建StringBuilder对象 + * + * @param sb 初始StringBuilder + * @param strs 初始字符串列表 + * @return StringBuilder对象 string builder + * @since 1.0.0 + */ + @Contract("_, _ -> param1") + public static StringBuilder appendBuilder(StringBuilder sb, @NotNull CharSequence... strs) { + for (CharSequence str : strs) { + sb.append(str); + } + return sb; + } + + /** + * 获得StringReader + * + * @param str 字符串 + * @return StringReader reader + * @since 1.0.0 + */ + @Contract("null -> null; !null -> new") + public static StringReader getReader(CharSequence str) { + if (null == str) { + return null; + } + return new StringReader(str.toString()); + } + + /** + * 获得StringWriter + * + * @return StringWriter writer + * @since 1.0.0 + */ + @NotNull + @Contract(value = " -> new", pure = true) + public static StringWriter getWriter() { + return new StringWriter(); + } + + + /** + * 统计指定内容中包含指定字符的数量 + * + * @param content 内容 + * @param charForSearch 被统计的字符 + * @return 包含数量 int + * @since 1.0.0 + */ + public static int count(CharSequence content, char charForSearch) { + int count = 0; + if (StringUtils.isEmpty(content)) { + return 0; + } + int contentLength = content.length(); + for (int i = 0; i < contentLength; i++) { + if (charForSearch == content.charAt(i)) { + count++; + } + } + return count; + } + + /** + * 下划线转驼峰 + * + * @param para 字符串 + * @return String string + * @since 1.0.0 + */ + @NotNull + public static String underlineToHump(@NotNull String para) { + return toHump(para, "_"); + } + + /** + * 驼峰转下划线 + * + * @param para 字符串 + * @return String string + * @since 1.0.0 + */ + @NotNull + public static String humpToUnderline(String para) { + return fromHump(para, "_"); + } + + /** + * 横线转驼峰 + * + * @param para 字符串 + * @return String string + * @since 1.0.0 + */ + @NotNull + public static String lineToHump(@NotNull String para) { + return toHump(para, "-"); + } + + /** + * 驼峰转横线 + * + * @param para 字符串 + * @return String string + * @since 1.0.0 + */ + @NotNull + public static String humpToLine(String para) { + return fromHump(para, "-"); + } + + /** + * To hump string + * + * @param para para + * @param s2 s 2 + * @return the string + * @since 1.0.0 + */ + @NotNull + private static String toHump(@NotNull String para, String s2) { + StringBuilder result = new StringBuilder(); + String[] a = para.split(s2); + for (String s : a) { + if (result.length() == 0) { + result.append(s.toLowerCase()); + } else { + result.append(s.substring(0, 1).toUpperCase()); + result.append(s.substring(1).toLowerCase()); + } + } + return result.toString(); + } + + /** + * From hump string + * + * @param para para + * @param s s + * @return the string + * @since 1.0.0 + */ + @NotNull + private static String fromHump(String para, String s) { + para = firstCharToLower(para); + StringBuilder sb = new StringBuilder(para); + int temp = 0; + for (int i = 0; i < para.length(); i++) { + if (Character.isUpperCase(para.charAt(i))) { + sb.insert(i + temp, s); + temp += 1; + } + } + return sb.toString().toLowerCase(); + } + + /** + * 重复某个字符串到指定长度 + * + * @param str 被重复的字符 + * @param padLen 指定长度 + * @return 重复字符字符串 string + * @since 4.3.2 + */ + @Contract("null, _ -> null") + private static String repeatByLength(CharSequence str, int padLen) { + if (null == str) { + return null; + } + if (padLen <= 0) { + return StringPool.EMPTY; + } + int strLen = str.length(); + if (strLen == padLen) { + return str.toString(); + } else if (strLen > padLen) { + return subPre(str, padLen); + } + + // 重复,直到达到指定长度 + char[] padding = new char[padLen]; + for (int i = 0; i < padLen; i++) { + padding[i] = str.charAt(i % strLen); + } + return new String(padding); + } + + /** + * 补充字符串以满足最小长度 + *
+     * StrUtil.padPre(null, *, *);//null
+     * StrUtil.padPre("1", 3, "ABC");//"AB1"
+     * StrUtil.padPre("123", 2, "ABC");//"12"
+     * 
+ * + * @param str 字符串 + * @param minLength 最小长度 + * @param padStr 补充的字符 + * @return 补充后的字符串 string + * @since 1.0.0 + */ + @Contract("null, _, _ -> null") + private static String padPre(CharSequence str, int minLength, CharSequence padStr) { + if (null == str) { + return null; + } + int strLen = str.length(); + if (strLen == minLength) { + return str.toString(); + } else if (strLen > minLength) { + return subPre(str, minLength); + } + + return repeatByLength(padStr, minLength - strLen).concat(str.toString()); + } + + /** + * 切割指定长度的后部分的字符串 + *
+     * StrUtil.subSufByLength("abcde", 3)      =    "cde"
+     * StrUtil.subSufByLength("abcde", 0)      =    ""
+     * StrUtil.subSufByLength("abcde", -5)     =    ""
+     * StrUtil.subSufByLength("abcde", -1)     =    ""
+     * StrUtil.subSufByLength("abcde", 5)       =    "abcde"
+     * StrUtil.subSufByLength("abcde", 10)     =    "abcde"
+     * StrUtil.subSufByLength(null, 3)               =    null
+     * 
+ * + * @param string 字符串 + * @param length 切割长度 + * @return 切割后后剩余的后半部分字符串 string + * @since 4.0.1 + */ + @Nullable + private static String subSufByLength(CharSequence string, int length) { + if (StringUtils.isEmpty(string)) { + return null; + } + if (length <= 0) { + return StringPool.EMPTY; + } + return sub(string, -length, string.length()); + } + + /** + * 补充字符串以满足最小长度 + *
+     * StrUtil.padAfter(null, *, *);//null
+     * StrUtil.padAfter("1", 3, "ABC");//"1AB"
+     * StrUtil.padAfter("123", 2, "ABC");//"23"
+     * 
+ * + * @param str 字符串,如果为null,按照空串处理 + * @param minLength 最小长度 + * @param padStr 补充的字符 + * @return 补充后的字符串 string + * @since 4.3.2 + */ + @Contract("null, _, _ -> null") + public static String padAfter(CharSequence str, int minLength, CharSequence padStr) { + if (null == str) { + return null; + } + int strLen = str.length(); + if (strLen == minLength) { + return str.toString(); + } else if (strLen > minLength) { + return subSufByLength(str, minLength); + } + + return str.toString().concat(repeatByLength(padStr, minLength - strLen)); + } + + /** + * {@link CharSequence} 转为字符串,null安全 + * + * @param cs {@link CharSequence} + * @return 字符串 string + * @since 1.0.0 + */ + @Contract("null -> null; !null -> !null") + public static String str(CharSequence cs) { + return null == cs ? null : cs.toString(); + } + + /** + * 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串 + *
+     * StrUtil.center(null, *, *)     = null
+     * StrUtil.center("", 4, " ")     = "    "
+     * StrUtil.center("ab", -1, " ")  = "ab"
+     * StrUtil.center("ab", 4, " ")   = " ab "
+     * StrUtil.center("abcd", 2, " ") = "abcd"
+     * StrUtil.center("a", 4, " ")    = " a  "
+     * StrUtil.center("a", 4, "yz")   = "yayz"
+     * StrUtil.center("abc", 7, null) = "  abc  "
+     * StrUtil.center("abc", 7, "")   = "  abc  "
+     * 
+ * + * @param str 字符串 + * @param size 指定长度 + * @param padStr 两边补充的字符串 + * @return 补充后的字符串 string + * @since 1.0.0 + */ + public static String center(CharSequence str, int size, CharSequence padStr) { + if (str == null || size <= 0) { + return str(str); + } + if (StringUtils.isEmpty(padStr)) { + padStr = StringPool.SPACE; + } + int strLen = str.length(); + int pads = size - strLen; + if (pads <= 0) { + return str.toString(); + } + str = padPre(str, strLen + pads / 2, padStr); + str = padAfter(str, size, padStr); + return str.toString(); + } + + /** + * 清理字符串,清理出某些不可见字符和一些sql特殊字符 + * + * @param txt 文本 + * @return {String} + * @since 1.0.0 + */ + @Contract("null -> null") + @Nullable + public static String cleanText(@Nullable String txt) { + if (txt == null) { + return null; + } + return SPECIAL_CHARS_REGEX.matcher(txt).replaceAll(StringPool.EMPTY); + } + + /** + * 获取标识符,用于参数清理 + * + * @param param 参数 + * @return 清理后的标识符 string + * @since 1.0.0 + */ + @Contract("null -> null") + @Nullable + public static String cleanIdentifier(@Nullable String param) { + if (param == null) { + return null; + } + StringBuilder paramBuilder = new StringBuilder(); + for (int i = 0; i < param.length(); i++) { + char c = param.charAt(i); + if (Character.isJavaIdentifierPart(c)) { + paramBuilder.append(c); + } + } + return paramBuilder.toString(); + } + + /** + * 删除空白符 + * + * @param str the str + * @return the string + * @since 1.0.0 + */ + public static String replaceBlank(String str) { + String dest = ""; + if (str != null) { + Pattern p = Pattern.compile(BLANK_SYMBOL); + Matcher m = p.matcher(str); + dest = m.replaceAll(""); + } + return dest; + } + + /** + * 生成uuid,采用 jdk 9 的形式,优化性能 + * + * @return UUID uuid + * @since 1.0.0 + */ + @NotNull + @Contract(" -> new") + public static String getUid() { + ThreadLocalRandom random = ThreadLocalRandom.current(); + long lsb = random.nextLong(); + long msb = random.nextLong(); + char[] buf = new char[32]; + formatUnsignedLong(lsb, buf, 20, 12); + formatUnsignedLong(lsb >>> 48, buf, 16, 4); + formatUnsignedLong(msb, buf, 12, 4); + formatUnsignedLong(msb >>> 16, buf, 8, 4); + formatUnsignedLong(msb >>> 32, buf, 0, 8); + return new String(buf); + } + + /** + * Format unsigned long * + * + * @param val val + * @param buf buf + * @param offset offset + * @param len len + * @since 1.0.0 + */ + private static void formatUnsignedLong(long val, @NotNull char[] buf, int offset, int len) { + int charPos = offset + len; + int radix = 1 << 4; + int mask = radix - 1; + do { + buf[--charPos] = NumberUtils.DIGITS[((int) val) & mask]; + val >>>= 4; + } while (charPos > offset); + } + +} + + + diff --git a/src/main/java/com/aos/fileidentify/util/function/DataSupplier.java b/src/main/java/com/aos/fileidentify/util/function/DataSupplier.java new file mode 100644 index 0000000..d6dcfb8 --- /dev/null +++ b/src/main/java/com/aos/fileidentify/util/function/DataSupplier.java @@ -0,0 +1,29 @@ +package com.aos.fileidentify.util.function; + +import com.baomidou.mybatisplus.core.metadata.IPage; + +import javax.validation.constraints.NotNull; + + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @param parameter + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:06 + * @since 0.0.1 + */ +public interface DataSupplier { + /** + * Get + * + * @param page page + * @param limit limit + * @return the page + * @since 2.3.0 + */ + @NotNull IPage get(int page, int limit); +} diff --git a/src/main/java/com/aos/fileidentify/util/pools/CharPool.java b/src/main/java/com/aos/fileidentify/util/pools/CharPool.java new file mode 100644 index 0000000..d2ab218 --- /dev/null +++ b/src/main/java/com/aos/fileidentify/util/pools/CharPool.java @@ -0,0 +1,109 @@ +package com.aos.fileidentify.util.pools; + +import lombok.experimental.UtilityClass; + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:26 + * @since 1.0.0 + */ +@UtilityClass +@SuppressWarnings("all") +public class CharPool { + /** UPPER_A */ + public static final char UPPER_A = 'A'; + /** LOWER_A */ + public static final char LOWER_A = 'a'; + /** UPPER_Z */ + public static final char UPPER_Z = 'Z'; + /** LOWER_Z */ + public static final char LOWER_Z = 'z'; + /** DOT */ + public static final char DOT = '.'; + /** AT */ + public static final char AT = '@'; + /** LEFT_BRACE */ + public static final char LEFT_BRACE = '{'; + /** RIGHT_BRACE */ + public static final char RIGHT_BRACE = '}'; + /** LEFT_BRACKET */ + public static final char LEFT_BRACKET = '('; + /** RIGHT_BRACKET */ + public static final char RIGHT_BRACKET = ')'; + /** DASH */ + public static final char DASH = '-'; + /** PERCENT */ + public static final char PERCENT = '%'; + /** PIPE */ + public static final char PIPE = '|'; + /** PLUS */ + public static final char PLUS = '+'; + /** QUESTION_MARK */ + public static final char QUESTION_MARK = '?'; + /** EXCLAMATION_MARK */ + public static final char EXCLAMATION_MARK = '!'; + /** EQUALS */ + public static final char EQUALS = '='; + /** AMPERSAND */ + public static final char AMPERSAND = '&'; + /** ASTERISK */ + public static final char ASTERISK = '*'; + /** STAR */ + public static final char STAR = ASTERISK; + /** BACK_SLASH */ + public static final char BACK_SLASH = '\\'; + /** COLON */ + public static final char COLON = ':'; + /** COMMA */ + public static final char COMMA = ','; + /** DOLLAR */ + public static final char DOLLAR = '$'; + /** SLASH */ + public static final char SLASH = '/'; + /** HASH */ + public static final char HASH = '#'; + /** HAT */ + public static final char HAT = '^'; + /** LEFT_CHEV */ + public static final char LEFT_CHEV = '<'; + /** NEWLINE */ + public static final char NEWLINE = '\n'; + /** N */ + public static final char N = 'n'; + /** Y */ + public static final char Y = 'y'; + /** QUOTE */ + public static final char QUOTE = '\"'; + /** RETURN */ + public static final char RETURN = '\r'; + /** TAB */ + public static final char TAB = '\t'; + /** RIGHT_CHEV */ + public static final char RIGHT_CHEV = '>'; + /** SEMICOLON */ + public static final char SEMICOLON = ';'; + /** SINGLE_QUOTE */ + public static final char SINGLE_QUOTE = '\''; + /** BACKTICK */ + public static final char BACKTICK = '`'; + /** SPACE */ + public static final char SPACE = ' '; + /** TILDA */ + public static final char TILDA = '~'; + /** LEFT_SQ_BRACKET */ + public static final char LEFT_SQ_BRACKET = '['; + /** RIGHT_SQ_BRACKET */ + public static final char RIGHT_SQ_BRACKET = ']'; + /** UNDERSCORE */ + public static final char UNDERSCORE = '_'; + /** ONE */ + public static final char ONE = '1'; + /** ZERO */ + public static final char ZERO = '0'; +} + diff --git a/src/main/java/com/aos/fileidentify/util/pools/StringPool.java b/src/main/java/com/aos/fileidentify/util/pools/StringPool.java new file mode 100644 index 0000000..031bc92 --- /dev/null +++ b/src/main/java/com/aos/fileidentify/util/pools/StringPool.java @@ -0,0 +1,132 @@ +package com.aos.fileidentify.util.pools; + +import lombok.experimental.UtilityClass; + +/** + *

Company: 成都返空汇网络技术有限公司

+ *

Description:

+ * + * @author yangjiyu + * @version 1.0.0 + * @email "mailto:yangjiyu@fkhwl.com" + * @date 2022.07.05 14:07 + * @since 1.0.0 + */ +@UtilityClass +public class StringPool { + + /** AMPERSAND */ + public static final String AMPERSAND = "&"; + /** AND */ + public static final String AND = "and"; + /** AT */ + public static final String AT = "@"; + /** ASTERISK */ + public static final String ASTERISK = "*"; + /** STAR */ + public static final String STAR = ASTERISK; + /** SLASH */ + public static final String SLASH = "/"; + /** DOUBLE_SLASH */ + public static final String DOUBLE_SLASH = "#//"; + /** COLON */ + public static final String COLON = ":"; + /** COMMA */ + public static final String COMMA = ","; + /** DASH */ + public static final String DASH = "-"; + /** DOLLAR */ + public static final String DOLLAR = "$"; + /** DOT */ + public static final String DOT = "."; + /** EMPTY */ + public static final String EMPTY = ""; + /** EMPTY_JSON */ + public static final String EMPTY_JSON = "{}"; + /** EQUALS */ + public static final String EQUALS = "="; + /** FALSE */ + public static final String FALSE = "false"; + /** HASH */ + public static final String HASH = "#"; + /** HAT */ + public static final String HAT = "^"; + /** LEFT_BRACE */ + public static final String LEFT_BRACE = "{"; + /** LEFT_BRACKET */ + public static final String LEFT_BRACKET = "("; + /** LEFT_CHEV */ + public static final String LEFT_CHEV = "<"; + /** NEWLINE */ + public static final String NEWLINE = "\n"; + /** N */ + public static final String N = "n"; + /** NO */ + public static final String NO = "no"; + /** NULL */ + public static final String NULL = "null"; + /** OFF */ + public static final String OFF = "off"; + /** ON */ + public static final String ON = "on"; + /** PERCENT */ + public static final String PERCENT = "%"; + /** PIPE */ + public static final String PIPE = "|"; + /** PLUS */ + public static final String PLUS = "+"; + /** QUESTION_MARK */ + public static final String QUESTION_MARK = "?"; + /** EXCLAMATION_MARK */ + public static final String EXCLAMATION_MARK = "!"; + /** QUOTE */ + public static final String QUOTE = "\""; + /** RETURN */ + public static final String RETURN = "\r"; + /** TAB */ + public static final String TAB = "\t"; + /** RIGHT_BRACE */ + public static final String RIGHT_BRACE = "}"; + /** RIGHT_BRACKET */ + public static final String RIGHT_BRACKET = ")"; + /** RIGHT_CHEV */ + public static final String RIGHT_CHEV = ">"; + /** SEMICOLON */ + public static final String SEMICOLON = ";"; + /** SINGLE_QUOTE */ + public static final String SINGLE_QUOTE = "'"; + /** BACKTICK */ + public static final String BACKTICK = "`"; + /** SPACE */ + public static final String SPACE = " "; + /** TILDA */ + public static final String TILDA = "~"; + /** LEFT_SQ_BRACKET */ + public static final String LEFT_SQ_BRACKET = "["; + /** RIGHT_SQ_BRACKET */ + public static final String RIGHT_SQ_BRACKET = "]"; + /** TRUE */ + public static final String TRUE = "true"; + /** UNDERSCORE */ + public static final String UNDERSCORE = "_"; + /** Y */ + public static final String Y = "y"; + /** YES */ + public static final String YES = "yes"; + /** ONE */ + public static final String ONE = "1"; + /** ZERO */ + public static final String ZERO = "0"; + /** DOLLAR_LEFT_BRACE */ + public static final String DOLLAR_LEFT_BRACE = "${"; + /** NULL_STRING */ + public static final String NULL_STRING = "N/A"; + /** any_Url_Patterns */ + public static final String ANY_URL_PATTERNS = SLASH + ASTERISK; + /** DOUBLE_ASTERISK */ + public static final String DOUBLE_ASTERISK = ASTERISK + ASTERISK; + /** any_PATH */ + public static final String ANY_PATH = SLASH + DOUBLE_ASTERISK; + + +}