From 52a4cb3d3bc4b84fee5c206ec11c6a6e177064bb Mon Sep 17 00:00:00 2001 From: esoe Date: Fri, 6 Sep 2024 17:00:15 +0300 Subject: [PATCH] qq --- .../controller/StorageController.java | 97 +++++++++++++++- .../ru/molokoin/storagers/model/XlsxCell.java | 104 ++---------------- .../model/XlsxMultipartDocument.java | 37 ++++++- .../storagers/model/educations/Building.java | 9 ++ .../storagers/model/educations/Course.java | 23 ++++ .../storagers/model/educations/Cretarea.java | 70 ++++++++++++ .../model/educations/EducationEntry.java | 22 ++++ .../storagers/model/educations/Headers.java | 49 +++++++++ .../model/educations/Organization.java | 18 +++ .../storagers/model/educations/Program.java | 26 +++++ .../storagers/model/educations/Student.java | 26 +++++ .../storagers/model/educations/Teacher.java | 11 ++ .../ru/molokoin/storagers/util/Stringer.java | 72 ++++++++++++ 13 files changed, 459 insertions(+), 105 deletions(-) create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Building.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Course.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Cretarea.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/EducationEntry.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Headers.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Organization.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Program.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Student.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Teacher.java create mode 100644 storage-rs/src/main/java/ru/molokoin/storagers/util/Stringer.java diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java b/storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java index a089f85..ad64071 100644 --- a/storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java +++ b/storage-rs/src/main/java/ru/molokoin/storagers/controller/StorageController.java @@ -2,6 +2,7 @@ package ru.molokoin.storagers.controller; import java.util.Arrays; import java.util.List; +import java.util.Map; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -16,7 +17,9 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import ru.molokoin.storagers.model.Document; +import ru.molokoin.storagers.model.XlsxCell; import ru.molokoin.storagers.model.XlsxDocument; +import ru.molokoin.storagers.model.XlsxMultipartDocument; import ru.molokoin.storagers.service.StorageServiceFace; /** @@ -29,11 +32,6 @@ import ru.molokoin.storagers.service.StorageServiceFace; @Controller @RequestMapping(path = "/", consumes = {"*/*"}) public class StorageController { - /** - * Подключаем сервис доступа к базе даных - */ - // private DocumentFace database; - /** * получаем в переменную root * значение свойства storage.location @@ -146,7 +144,7 @@ public class StorageController { /** * Получение метаданных о файле * @param filename - * @return + * @return ResponseEntity */ @GetMapping("/api/document/{filename}") public ResponseEntity getDocumentByName(@PathVariable String filename){ @@ -165,6 +163,93 @@ public class StorageController { return new ResponseEntity<>(xlsx, HttpStatus.OK); } + /** + * Получение содержимого файла в json формате + * данные предоставляются построчно + * @param filename + * @return + */ + @GetMapping("/api/document/{filename}/content/line/{line}") + public ResponseEntity getDocumentContentByLines(@PathVariable String filename, @PathVariable String line){ + Document doc = storage.find(filename); + XlsxMultipartDocument parts = new XlsxMultipartDocument(doc); + List cells = parts.line(Integer.parseInt(line)); + return new ResponseEntity<>(cells, HttpStatus.OK); + } + + + @GetMapping("/api/document/{filename}/content/part/{from}/{count}") + public ResponseEntity getDocumentContentByParts(@PathVariable String filename, @PathVariable String from, @PathVariable String count){ + Document doc = storage.find(filename); + XlsxMultipartDocument parts = new XlsxMultipartDocument(doc); + // System.out.println(parts.getLineCount()); + Map> cells = parts.lines(Integer.parseInt(from), Integer.parseInt(count)); + return new ResponseEntity<>(cells, HttpStatus.OK); + } + + @GetMapping("/api/document/{filename}/content/length") + public ResponseEntity getDocumentContentLenght(@PathVariable String filename){ + Document doc = storage.find(filename); + XlsxMultipartDocument parts = new XlsxMultipartDocument(doc); + return new ResponseEntity<>(parts.getLineCount(), HttpStatus.OK); + } + + /** + * Получение одного столбца в json формате + * @param filename + * @return + */ + @GetMapping("/api/document/{filename}/content/column/{num}") + public ResponseEntity getDocumentContentByColumn(@PathVariable String filename, @PathVariable String num){ + Document doc = storage.find(filename); + XlsxMultipartDocument parts = new XlsxMultipartDocument(doc); + List cells = parts.column(Integer.parseInt(num)); + return new ResponseEntity<>(cells, HttpStatus.OK); + } + + /** + * получение списка уникальных эементов в столбце + * @param filename + * @return + */ + @GetMapping("/api/document/{filename}/content/column/{num}/unique") + public ResponseEntity getDocumentContentByColumnUnique(@PathVariable String filename, @PathVariable String num){ + Document doc = storage.find(filename); + XlsxMultipartDocument parts = new XlsxMultipartDocument(doc); + List cells = parts.columnUnique(Integer.parseInt(num)); + return new ResponseEntity<>(cells, HttpStatus.OK); + } + + /* + * TODO : сортировка + * - получение уникальных элементов столбца, + * отсортированных по алфавиту + * отсортированных по возростанию/убыванию + * + * sort-up + * sort-down + * - сортировка данных в выборке (part) + * + * TODO : фильтрация + * - получение данных (lines) по определенному значению в столбце + * в запросе указываем номер столбца, + * значение передаем атрибутом к запросу + */ + /** + * + * @param filename + * @return + */ + + + + + + + + + + /** * Удаление файла по имени */ diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java index 54e4558..445d3f0 100644 --- a/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxCell.java @@ -3,20 +3,18 @@ package ru.molokoin.storagers.model; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DateUtil; +import ru.molokoin.storagers.util.Stringer; + /** * Класс для хранения содержимого ячейки * TODO: убрать не нужные поля */ public class XlsxCell { private String content; //содержимое ячейки - private String textColor; //цвет шрифта - private String bgColor; // цвет заливки ячейки - private String textSize; //8-12-14-24 размеры шрифта - private int textWeight; //жирность: bold (900), normal(500), private String type;// STRING, NUMERIC, BOOLEAN, FORMULA public XlsxCell(String content){ - this.content = content; + setContent(content); } /** @@ -30,63 +28,9 @@ public class XlsxCell { * @param content the content to set */ public void setContent(String content) { - this.content = content; - } - - /** - * @return the textColor - */ - public String getTextColor() { - return textColor; - } - - /** - * @param textColor the textColor to set - */ - public void setTextColor(String textColor) { - this.textColor = textColor; - } - - /** - * @return the bgColor - */ - public String getBgColor() { - return bgColor; - } - - /** - * @param bgColor the bgColor to set - */ - public void setBgColor(String bgColor) { - this.bgColor = bgColor; - } - - /** - * @return the textSize - */ - public String getTextSize() { - return textSize; - } - - /** - * @param textSize the textSize to set - */ - public void setTextSize(String textSize) { - this.textSize = textSize; - } - - /** - * @return the textWeight - */ - public int getTextWeight() { - return textWeight; - } - - /** - * @param textWeight the textWeight to set - */ - public void setTextWeight(int textWeight) { - this.textWeight = textWeight; + //убираем лишние пробельные символы + //заменяем пустые строки на "" + this.content = Stringer.clear(content); } /** @@ -108,10 +52,6 @@ public class XlsxCell { final int prime = 31; int result = 1; result = prime * result + ((content == null) ? 0 : content.hashCode()); - result = prime * result + ((textColor == null) ? 0 : textColor.hashCode()); - result = prime * result + ((bgColor == null) ? 0 : bgColor.hashCode()); - result = prime * result + ((textSize == null) ? 0 : textSize.hashCode()); - result = prime * result + textWeight; result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } @@ -130,23 +70,6 @@ public class XlsxCell { return false; } else if (!content.equals(other.content)) return false; - if (textColor == null) { - if (other.textColor != null) - return false; - } else if (!textColor.equals(other.textColor)) - return false; - if (bgColor == null) { - if (other.bgColor != null) - return false; - } else if (!bgColor.equals(other.bgColor)) - return false; - if (textSize == null) { - if (other.textSize != null) - return false; - } else if (!textSize.equals(other.textSize)) - return false; - if (textWeight != other.textWeight) - return false; if (type == null) { if (other.type != null) return false; @@ -157,8 +80,7 @@ public class XlsxCell { @Override public String toString() { - return "XlsxCell [content=" + content + ", textColor=" + textColor + ", bgColor=" + bgColor + ", textSize=" - + textSize + ", textWeight=" + textWeight + ", type=" + type + "]"; + return "XlsxCell [content=" + content + ", type=" + type + "]"; } /** @@ -175,13 +97,9 @@ public class XlsxCell { * @param textWeight * @param type */ - public XlsxCell(String content, String textColor, String bgColor, String textSize, int textWeight, String type) { - this.content = content; - this.textColor = textColor; - this.bgColor = bgColor; - this.textSize = textSize; - this.textWeight = textWeight; - this.type = type; + public XlsxCell(String content, String type) { + this.setContent(content); + this.setType(type); } /** @@ -193,7 +111,7 @@ public class XlsxCell { //обработка null if (cell == null) { this.setContent(""); - this.type = "NULL"; + this.setType("NULL"); return; } diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxMultipartDocument.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxMultipartDocument.java index 2d089f2..2f235a7 100644 --- a/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxMultipartDocument.java +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/XlsxMultipartDocument.java @@ -9,14 +9,11 @@ import java.util.List; import java.util.Map; import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.springframework.web.multipart.MultipartFile; -import jakarta.annotation.sql.DataSourceDefinition; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -61,8 +58,10 @@ public class XlsxMultipartDocument { List cells = new ArrayList<>(); if (row == null) return cells; //пустая строка - //перебор ячейек в строке - for (Cell cell : row) { + int i = 0; + int max = row.getLastCellNum(); + for (; i < max; i++) { + Cell cell = row.getCell(i); cells.add(new XlsxCell(cell)); } return cells; @@ -75,6 +74,32 @@ public class XlsxMultipartDocument { } catch (IOException e) { System.out.println("Не удалось закрыть потоки: " + e.getMessage()); } - } + + public Map> lines(int from, int count) { + Map> lines = new HashMap<>(); + for (int i = from; i < from + count; i++) { + lines.put(i, line(i)); + } + return lines; + } + + public List column(int num) { + List cells = new ArrayList<>(); + for (int i = 0; i < getLineCount(); i++) { + cells.add(line(i).get(num)); + } + return cells; + } + + public List columnUnique(int num) { + List cells = new ArrayList<>(); + for (int i = 0; i < getLineCount(); i++) { + if (!cells.contains(line(i).get(num))) + cells.add(line(i).get(num)); + } + return cells; + } + + } diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Building.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Building.java new file mode 100644 index 0000000..8d617e7 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Building.java @@ -0,0 +1,9 @@ +package ru.molokoin.storagers.model.educations; + +public class Building { + private long id; + private String name_short;//Сокращенное наименование (абревиатура) + private String name_full;//Полное наименование + private String code_short;//Краткий код + private String code_full;//Полный код +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Course.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Course.java new file mode 100644 index 0000000..f5321b6 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Course.java @@ -0,0 +1,23 @@ +package ru.molokoin.storagers.model.educations; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Course { + private long id;//уникальный идентификатор курса + private String place;//место проведения занятий + private Date start_date;//дата начала курса + private Date protocol_date;//дата протокола + private String protocol_number;//номер протокола + private String report_period;//отчетный период (наименование месяца) + private Teacher teacher;//сведения о преподаватле + private Program program;//сведения о программе обучения + private Building building;//сведения об объекте строиbernate + +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Cretarea.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Cretarea.java new file mode 100644 index 0000000..4315deb --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Cretarea.java @@ -0,0 +1,70 @@ +package ru.molokoin.storagers.model.educations; + +import java.util.List; +import java.util.Map.Entry; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import ru.molokoin.storagers.model.XlsxCell; +import ru.molokoin.storagers.util.Stringer; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Cretarea { + private long id; + private String name;//Наименование + private String nameShort;//Наименование : сокращенно + + public Cretarea(String nameShort) { + setNameShort(nameShort); + } + + public Cretarea(List cells) { + this(cells.get(Headers.CRETAREA_NAME_SHORT.column()).getContent()); + } + + public Cretarea(Entry> entry) { + this(entry.getValue()); + } + + public void setNameShort(String nameShort) { + if (!Stringer.isEmpty(nameShort)){ + this.nameShort = Stringer.clear(nameShort); + } else { + this.nameShort = ""; + } + } + + public String getNameShort() { + return this.nameShort; + } + + /** + * Сравнение критериев по полю name_short - "Наименование : сокращенно" + * остальные поля будут пустыми при чтении документа + * + * @param cretarea + * @return true - если совпадают + */ + public boolean isSimilar(Cretarea cretarea) { + return this.nameShort.equals(cretarea.getNameShort()); + } + + /** + * Проверка наличия сокращенного наименования критерия + * @return true - если пусто + */ + public boolean isEmpty() { + return this.nameShort == null + || this.nameShort.isEmpty() + || this.nameShort.trim().isEmpty() + || this.nameShort.equals(""); + } + + + +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/EducationEntry.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/EducationEntry.java new file mode 100644 index 0000000..6f18dba --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/EducationEntry.java @@ -0,0 +1,22 @@ +package ru.molokoin.storagers.model.educations; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class EducationEntry { + private long id; + private String sertificate_number;//номер удостоверения + private String frdo_number;//ФРДО номер по реестру + private String eisot_number;//ЕИСОТ номер по реестру + private String ones;//единички (вспомогатльный столбец) + private Course course;//сведения о курсе + private Student student;//сведения о студенте + + + + +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Headers.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Headers.java new file mode 100644 index 0000000..5028c45 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Headers.java @@ -0,0 +1,49 @@ +package ru.molokoin.storagers.model.educations; + +/** + * Список заголовков таблицы + * добавить поле, для хранения типа данных столбца + */ +public enum Headers { + + ORGANIZATION_TYPE(0, "Тип организации"), + ORGANIZATION_NAME_FULL(1, "ПСК"), + STUDENT_DIRECTION(2, "Структурное подразделение"), + STUDENT_FULL_NAME(3, "ФИО обучающегося"), + STUDENT_PROFESSION(4, "Профессия"), + COURSE_PLACE(5, "Место проведения обучения"), + PROGRAM_NAME(6, "Программа обучения"), + COURSE_START_DATE(7, "Дата начала обучения"), + PROGRAM_LENGHT(8, "Продолжительность программы"), + COURSE_PROTOCOL_DATE(9, "Дата протокола"), + STUDENT_CATEGORY(10, "Категория обучаемых"), + PROGRAMM_STADY_DIRECTION(11, "Направление обучения"), + CRETAREA_NAME_SHORT(12, "Критерий"), + COURSE_PROTOCOL_NUMBER(13, "Номер протокола"), + EDUCATION_SERTIFICATE_NUMBER(14, "Номер удостоверения"), + PROGRAM_PRICE(15, "Стоимость обучения"), + EDUCATIONS_ONES(16, "Единички"), + COURSE_REPORT_PERIOD(17, "Отчетный период"), + TEACHER_FULL_NAME(18, "Преподаватель"), + BUILDING_NAME_SHORT(19, "Объект"); + + + private Headers(int column, String title) { + this.column = column; + this.title = title; + } + + public int column() { + return column; + } + + public String title() { + return title; + } + + private int column; + private String title; + + + +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Organization.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Organization.java new file mode 100644 index 0000000..edf888b --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Organization.java @@ -0,0 +1,18 @@ +package ru.molokoin.storagers.model.educations; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Organization { + private long id; + private String ownership;//Форма собственности ПСК + private String name_short;//Сокращенное наименование + private String name_full;//Полное наименование (1) + private String type;//вид ПСК - производственная/сервисная (0) + private String inn;//ИНН организации + +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Program.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Program.java new file mode 100644 index 0000000..c993405 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Program.java @@ -0,0 +1,26 @@ +package ru.molokoin.storagers.model.educations; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Program { + private long id; + private String name;//Наименование + private Integer lenght;//длительность программы в часах + + /** + * Направление обучения: + * - Обязательное обучение + * - Производственное обучение + * - Обучение вновь внедряемым процедурам + * - Обучение водителей + */ + private String study_direction; + private Integer price;//рублей + private Cretarea cretarea; + +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Student.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Student.java new file mode 100644 index 0000000..a258340 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Student.java @@ -0,0 +1,26 @@ +package ru.molokoin.storagers.model.educations; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +@Data +public class Student { + private long id; + private String first_name;//Имя + private String second_name;//Отчество + private String last_name;//Фамилия + private String profession;//Профессия + private String category;//Категория (ИТР или рабочий) + private String direction;//Структурное подразделение + private String snils;//СНИЛС + private Date berth;//Дата рождения + private String sitizenship;//Гражданство + private String sex;//Пол (Муж/Жен) + private Organization organization;//Организация - работодатель + +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Teacher.java b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Teacher.java new file mode 100644 index 0000000..9d78614 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/model/educations/Teacher.java @@ -0,0 +1,11 @@ +package ru.molokoin.storagers.model.educations; + +public class Teacher { + private long id; + private String first_name;//Имя + private String second_name;//Фамилия + private String last_name;//Отчество + private String employee_id; + private String snils; + +} diff --git a/storage-rs/src/main/java/ru/molokoin/storagers/util/Stringer.java b/storage-rs/src/main/java/ru/molokoin/storagers/util/Stringer.java new file mode 100644 index 0000000..3e89874 --- /dev/null +++ b/storage-rs/src/main/java/ru/molokoin/storagers/util/Stringer.java @@ -0,0 +1,72 @@ +package ru.molokoin.storagers.util; + +/** + * Класс для работы со строками + */ +public class Stringer { + + /** + * Проверяет, является ли переданная строка null, пустой строкой или состоит только из пробелов. + * + * @param str Строка для проверки + * @return True если строка является null, пустой строкой или состоит только из пробелов + * False в противном случае + */ + public static Boolean checkForEmpty(String str) { + // Check if the string is null + if (str == null) { + return true; + } + // Check if the string is empty or consists only of whitespace characters + if (str.isEmpty() || str.trim().isEmpty()) { + return true; + } + // The string is not null, not empty and does not consist only of whitespace characters + return false; + } + + /** + * Удаляет регулярным выражением лишние пробельные символы из строки. + * + * Заменяет знаки переноса строки на пробелы с помощью использования регулярного выражения + * \s+ - пробелы (и все ниже приведенные пробельные символы) + * \t - табуляция + * \v - вертикальная табуляция + * \r - перенос в начало строки + * \n - перенос строки + * \f - форматированный перенос строки + * + * Осавляет по одному пробелу между словами, если слов больше одного + * Возвращает пустую строку, если получена строка null + * + * @param string строка для обработки + * @return строку без лишних пробелов или пустую строку + */ + public static String clear(String string) { + // Проверяем, не является ли строка null. Если строка null, возвращаем пустую строку. + if (string == null) { + return ""; + } + + // Удаляем лишние пробелы из строки. + return string.replaceAll("\\s+", " ").trim(); + } + + /** + * + * @param str + * @return + */ + public static boolean isEmpty(String str) { + // Check if the string is null + if (str == null) { + return true; + } + // Check if the string is empty or consists only of whitespace characters + if (str.isEmpty() || str.trim().isEmpty()) { + return true; + } + // The string is not null, not empty and does not consist only of whitespace characters + return false; + } +}