diff --git a/pom.xml b/pom.xml index 522d8ab..37d7967 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.sadtech.autoresponder autoresponder - 1.6.2-RELEASE + 1.6.3-SNAPSHOT jar @@ -24,6 +24,7 @@ 1.7.26 + 4.12 @@ -36,7 +37,13 @@ junit junit - 4.12 + ${junit.ver} + + + + org.projectlombok + lombok + 1.18.6 diff --git a/src/main/java/org/sadtech/autoresponder/Autoresponder.java b/src/main/java/org/sadtech/autoresponder/Autoresponder.java index fa8b8bf..d23ace1 100644 --- a/src/main/java/org/sadtech/autoresponder/Autoresponder.java +++ b/src/main/java/org/sadtech/autoresponder/Autoresponder.java @@ -1,13 +1,16 @@ package org.sadtech.autoresponder; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; import org.sadtech.autoresponder.compare.UnitPriorityComparator; import org.sadtech.autoresponder.entity.Unit; import org.sadtech.autoresponder.entity.UnitPointer; import org.sadtech.autoresponder.exception.NotFoundUnitException; import org.sadtech.autoresponder.service.UnitPointerService; +import org.sadtech.autoresponder.util.Description; import org.sadtech.autoresponder.util.Parser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.Optional; @@ -15,16 +18,26 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -/* - Отвечает за функционирование автоответчика +/** + * Реализуют основную логику автоответчика. + * + * @author upagge [07/07/2019] */ +@Slf4j public class Autoresponder { - private static final Logger log = LoggerFactory.getLogger(Autoresponder.class); + @Description("Компоратор для сортировки Unit-ов") private static final UnitPriorityComparator UNIT_PRIORITY_COMPARATOR = new UnitPriorityComparator(); + @Description("Начальные юниты, первый запрос приходит на них") private final Set startUnits; + + @Getter + @Setter + @Description("Дефолтный юнит, отправляется если ни один Unit не подошел") private Unit defaultUnit; + + @Getter private final UnitPointerService unitPointerService; public Autoresponder(UnitPointerService unitPointerService, Set startUnits) { @@ -32,19 +45,14 @@ public class Autoresponder { this.unitPointerService = unitPointerService; } - public UnitPointerService getUnitPointerService() { - return unitPointerService; - } - - public void setDefaultUnit(Unit defaultUnit) { - this.defaultUnit = defaultUnit; - } - - public Unit getDefaultUnit() { - return defaultUnit; - } - - public Unit answer(Integer personId, String message) { + /** + * Принимает текстовый запрос пользователя и отдает юнит, который соответствует запросу + * + * @param personId Идентификатор пользователя + * @param message Запрос пользователя - текстовое сообщение + * @return {@link Unit}, который отвечает за данные для обработки данного запроса + */ + public Unit answer(@NonNull Integer personId, String message) { UnitPointer unitPointer = checkAndAddPerson(personId); Unit unit; try { @@ -60,6 +68,13 @@ public class Autoresponder { return Optional.ofNullable(unit).orElseThrow(NotFoundUnitException::new); } + /** + * Выбирает, какой {@link Unit} будет отдан для обработки + * + * @param nextUnits Множество следующих Unit-ов + * @param message Запрос пользователя - текстовое сообщение + * @return Юнит, который нуждается в обработке в соответствии с запросом пользователя + */ private Unit nextUnit(Set nextUnits, String message) { Optional unit = nextUnits.stream() .filter(nextUnit -> nextUnit.getPattern() != null && patternReg(nextUnit, message)) @@ -79,6 +94,12 @@ public class Autoresponder { return unit.orElseThrow(NotFoundUnitException::new); } + /** + * Проверяет наличие {@link UnitPointer} у пользовтеля и создает его, если не находит + * + * @param personId Идентификатор пользователя + * @return {@link UnitPointer}, который сохраняет {@link Unit}, который был обработан последним + */ private UnitPointer checkAndAddPerson(Integer personId) { UnitPointer unitPointer; if (unitPointerService.check(personId)) { @@ -90,6 +111,7 @@ public class Autoresponder { return unitPointer; } + private boolean patternReg(Unit unit, String message) { Pattern pattern = unit.getPattern(); Matcher m = pattern.matcher(message); diff --git a/src/main/java/org/sadtech/autoresponder/compare/UnitPriorityComparator.java b/src/main/java/org/sadtech/autoresponder/compare/UnitPriorityComparator.java index 1f33e56..7b13c47 100644 --- a/src/main/java/org/sadtech/autoresponder/compare/UnitPriorityComparator.java +++ b/src/main/java/org/sadtech/autoresponder/compare/UnitPriorityComparator.java @@ -4,6 +4,11 @@ import org.sadtech.autoresponder.entity.Unit; import java.util.Comparator; +/** + * Компоратор для сортировки {@link Unit} по приоритету. + * + * @author upagge [07/07/2019] + */ public class UnitPriorityComparator implements Comparator { @Override diff --git a/src/main/java/org/sadtech/autoresponder/entity/Unit.java b/src/main/java/org/sadtech/autoresponder/entity/Unit.java index 3880082..a27d3f7 100644 --- a/src/main/java/org/sadtech/autoresponder/entity/Unit.java +++ b/src/main/java/org/sadtech/autoresponder/entity/Unit.java @@ -1,20 +1,40 @@ package org.sadtech.autoresponder.entity; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.sadtech.autoresponder.util.Description; + import java.util.Arrays; import java.util.HashSet; -import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; -/* - Абстрактный класс, предпологающий какие-то действия +/** + * Абстрактная сущность, отвечающая за хранение данных, необходимая для обработки запроса. + * + * @author upagge [07/07/2019] */ +@Getter +@EqualsAndHashCode public abstract class Unit { + @Description("Ключевые слова") private Set keyWords; + + @Setter + @Description("Регулярное выражение") private Pattern pattern; + + @Setter + // todo [upagge] [07/07/2019]: Придумать нормальное описание private Integer matchThreshold = 10; + + @Setter + @Description("Значение приоритета") private Integer priority = 10; + + @Description("Множество следующих Unit в сценарии") private Set nextUnits; public void setKeyWord(String... keyWord) { @@ -31,10 +51,6 @@ public abstract class Unit { this.keyWords.addAll(keyWords); } - public Set getKeyWords() { - return keyWords; - } - public void setNextUnit(Unit... unit) { if (nextUnits == null) { nextUnits = new HashSet<>(); @@ -49,48 +65,4 @@ public abstract class Unit { this.nextUnits.addAll(nextUnits); } - public Set getNextUnits() { - return nextUnits; - } - - public Integer getMatchThreshold() { - return matchThreshold; - } - - public void setMatchThreshold(Integer matchThreshold) { - this.matchThreshold = matchThreshold; - } - - public Integer getPriority() { - return priority; - } - - public void setPriority(Integer priority) { - this.priority = priority; - } - - public Pattern getPattern() { - return pattern; - } - - public void setPattern(Pattern pattern) { - this.pattern = pattern; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Unit)) return false; - Unit unit = (Unit) o; - return Objects.equals(keyWords, unit.keyWords) && - Objects.equals(pattern, unit.pattern) && - Objects.equals(matchThreshold, unit.matchThreshold) && - Objects.equals(priority, unit.priority) && - Objects.equals(nextUnits, unit.nextUnits); - } - - @Override - public int hashCode() { - return Objects.hash(keyWords, pattern, matchThreshold, priority, nextUnits); - } } diff --git a/src/main/java/org/sadtech/autoresponder/entity/UnitPointer.java b/src/main/java/org/sadtech/autoresponder/entity/UnitPointer.java index 271c5c4..9b19434 100644 --- a/src/main/java/org/sadtech/autoresponder/entity/UnitPointer.java +++ b/src/main/java/org/sadtech/autoresponder/entity/UnitPointer.java @@ -1,59 +1,26 @@ package org.sadtech.autoresponder.entity; -import java.util.Objects; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.sadtech.autoresponder.util.Description; -/* - Сохраняет юнит, на котором остановился пользователь. +/** + * Сущность для сохранения позиции пользователя в сценарии, состоящем из связного списка элементов {@link Unit}. + * + * @author upagge [07/07/2019] */ +@Data +@AllArgsConstructor public class UnitPointer { + @Description("Идентификатор пользователя") private Integer entityId; - private Unit unit; - public UnitPointer(Integer entityId, Unit unit) { - this.entityId = entityId; - this.unit = unit; - } + @Description("Юнит, который был обработан") + private Unit unit; public UnitPointer(Integer entityId) { this.entityId = entityId; } - public Integer getEntityId() { - return entityId; - } - - public void setEntityId(Integer entityId) { - this.entityId = entityId; - } - - public Unit getUnit() { - return unit; - } - - public void setUnit(Unit unit) { - this.unit = unit; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - UnitPointer unitPointer = (UnitPointer) o; - return Objects.equals(entityId, unitPointer.entityId) && - Objects.equals(unit, unitPointer.unit); - } - - @Override - public int hashCode() { - return Objects.hash(entityId, unit); - } - - @Override - public String toString() { - return "UnitPointer{" + - "entityId=" + entityId + - ", unit=" + unit + - '}'; - } } diff --git a/src/main/java/org/sadtech/autoresponder/exception/NotFoundUnitException.java b/src/main/java/org/sadtech/autoresponder/exception/NotFoundUnitException.java index bb8be59..708ec1b 100644 --- a/src/main/java/org/sadtech/autoresponder/exception/NotFoundUnitException.java +++ b/src/main/java/org/sadtech/autoresponder/exception/NotFoundUnitException.java @@ -1,4 +1,9 @@ package org.sadtech.autoresponder.exception; +/** + * Исключение, которое выбрасывается, если юнит не найден. + * + * @author upagge [07/07/2019] + */ public class NotFoundUnitException extends RuntimeException { } diff --git a/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepository.java b/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepository.java index acd74fb..58bfc5d 100644 --- a/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepository.java +++ b/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepository.java @@ -4,6 +4,11 @@ import org.sadtech.autoresponder.entity.UnitPointer; import java.util.Collection; +/** + * Интегрфейс для работы с хранилищем сущности {@link UnitPointer}. + * + * @author upagge [07/07/2019] + */ public interface UnitPointerRepository { void add(UnitPointer unitPointer); @@ -12,8 +17,12 @@ public interface UnitPointerRepository { void remove(Integer entityId); - void addAll(Collection unitPointerMap); + void addAll(Collection unitPointers); + /** + * @param entityId Идентификатор пользователя + * @return Объект с последним обработанным {@link org.sadtech.autoresponder.entity.Unit} для пользователя + */ UnitPointer findByEntityId(Integer entityId); } diff --git a/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepositoryMap.java b/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepositoryMap.java index f093d46..4f606b2 100644 --- a/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepositoryMap.java +++ b/src/main/java/org/sadtech/autoresponder/repository/UnitPointerRepositoryMap.java @@ -6,6 +6,11 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +/** + * Реализация хранилища для {@link UnitPointer} на основе Map. + * + * @author upagge [07/07/2019] + */ public class UnitPointerRepositoryMap implements UnitPointerRepository { private Map unitPointerMap = new HashMap<>(); diff --git a/src/main/java/org/sadtech/autoresponder/service/UnitPointerService.java b/src/main/java/org/sadtech/autoresponder/service/UnitPointerService.java index b174eea..381167d 100644 --- a/src/main/java/org/sadtech/autoresponder/service/UnitPointerService.java +++ b/src/main/java/org/sadtech/autoresponder/service/UnitPointerService.java @@ -3,10 +3,20 @@ package org.sadtech.autoresponder.service; import org.sadtech.autoresponder.entity.Unit; import org.sadtech.autoresponder.entity.UnitPointer; +/** + * Сервис для взаимодействия с сущностью {@link UnitPointer}. + * + * @author upagge [07/07/2019] + */ public interface UnitPointerService { void add(UnitPointer unitPointer); + /** + * Проверка наличия {@link UnitPointer} для пользователя + * @param entityId Идентификатор пользователя + * @return true - если найдено + */ boolean check(Integer entityId); UnitPointer getByEntityId(Integer entityId); diff --git a/src/main/java/org/sadtech/autoresponder/service/UnitPointerServiceImpl.java b/src/main/java/org/sadtech/autoresponder/service/UnitPointerServiceImpl.java index 05bea40..94d7693 100644 --- a/src/main/java/org/sadtech/autoresponder/service/UnitPointerServiceImpl.java +++ b/src/main/java/org/sadtech/autoresponder/service/UnitPointerServiceImpl.java @@ -1,16 +1,14 @@ package org.sadtech.autoresponder.service; +import lombok.extern.slf4j.Slf4j; import org.sadtech.autoresponder.entity.Unit; import org.sadtech.autoresponder.entity.UnitPointer; import org.sadtech.autoresponder.repository.UnitPointerRepository; import org.sadtech.autoresponder.repository.UnitPointerRepositoryMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +@Slf4j public class UnitPointerServiceImpl implements UnitPointerService { - private static final Logger log = LoggerFactory.getLogger(UnitPointerServiceImpl.class); - private UnitPointerRepository unitPointerRepository; public UnitPointerServiceImpl() { diff --git a/src/main/java/org/sadtech/autoresponder/util/Description.java b/src/main/java/org/sadtech/autoresponder/util/Description.java new file mode 100644 index 0000000..dcb42ce --- /dev/null +++ b/src/main/java/org/sadtech/autoresponder/util/Description.java @@ -0,0 +1,17 @@ +package org.sadtech.autoresponder.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Служит для описания роли полей в классах. + * + * @author upagge [07/07/2019] + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.SOURCE) +public @interface Description { + String value(); +} diff --git a/src/main/java/org/sadtech/autoresponder/util/Parser.java b/src/main/java/org/sadtech/autoresponder/util/Parser.java index 4466194..da76c27 100644 --- a/src/main/java/org/sadtech/autoresponder/util/Parser.java +++ b/src/main/java/org/sadtech/autoresponder/util/Parser.java @@ -1,5 +1,6 @@ package org.sadtech.autoresponder.util; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; @@ -7,11 +8,14 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; -/* - Возвращает Set слов из текста +/** + * Разбивает строку на множество слов, удаляя предлоги. + * + * @author upagge [07/07/2019] */ public class Parser { + @Description("Множество предлогов") private static final Set pretexts = Stream .of("в", "без", "до", "из", "к", "на", "по", "о", "от", "перед", "при", "с", "у", "за", "над", "об", "под", "про", "для") @@ -21,13 +25,14 @@ public class Parser { throw new IllegalStateException("Utility Class"); } + /** + * Метод по разбиению строки на множество слов + * @param text Строка + * @return Множество слов + */ public static Set parse(String text) { - Pattern p = Pattern.compile("[а-яА-Я0-9]+"); - Matcher m = p.matcher(text); - Set words = new HashSet<>(); - while (m.find()) { - words.add(m.group().toLowerCase()); - } + String[] split = text.split("\\P{L}+"); + Set words = new HashSet<>(Arrays.asList(split)); words.removeAll(pretexts); return words; }