more detailed error messages, recursion prevention, stacktrace doesn't print on error anymore, xml fix, some other minor fixes

This commit is contained in:
Egor 2022-03-20 14:33:20 +03:00
parent e36983b378
commit 5a3877c86b
11 changed files with 141 additions and 46 deletions

View file

@ -15,7 +15,7 @@ public class Lab5 {
try {
peopleDatabase.load();
} catch (Database.DatabaseLoadFailedException e) {
System.out.println("Не удалось загрузить коллекцию из файла");
System.out.println(e.getMessage());
}
PeopleDatabaseCommands.setPeopleDatabase(peopleDatabase);

View file

@ -19,6 +19,7 @@ import java.util.TreeSet;
/**
* Класс базы данных людей, реализующий интерфейс Database
*
* @see ru.erius.lab5.collection.Database
*/
@XmlRootElement
@ -33,9 +34,14 @@ public class PeopleDatabase implements Database {
private JAXBContext context;
@XmlTransient
private File file;
@Getter @XmlElement(name = "person")
@XmlTransient
private String errorMessage;
@Getter
@XmlElement(name = "person")
private TreeSet<Person> collection = new TreeSet<>();
@Getter @XmlJavaTypeAdapter(LocalDateAdapter.class) @XmlElement(name = "initDate")
@Getter
@XmlJavaTypeAdapter(LocalDateAdapter.class)
@XmlElement(name = "initDate")
private LocalDate initDate = LocalDate.now();
{
@ -50,7 +56,7 @@ public class PeopleDatabase implements Database {
return String.format("Тип коллекции: %s \n" +
"Дата инициализации: %s \n" +
"Количество элементов: %d \n",
TYPE, this.initDate, this.collection.size());
TYPE, this.initDate, this.collection.size());
}
/**
@ -58,27 +64,35 @@ public class PeopleDatabase implements Database {
* переменной окружения {@link #ENV_VAR}
*
* @throws Database.DatabaseLoadFailedException если переменная окружения {@link #ENV_VAR} не задана,
* файла не существует, либо отсутствуют права на запись или чтение
* файла не существует, либо отсутствуют права на запись или чтение
*/
@Override
public void load() throws Database.DatabaseLoadFailedException {
System.out.println("Инициализация коллекции из файла...");
String path = System.getenv(ENV_VAR);
if (path == null)
if (path == null) {
errorMessage = "Не найдена переменная окружения LAB5_PATH";
throw new DatabaseLoadFailedException("Не найдена переменная окружения LAB5_PATH");
file = new File(path);
}
File file = new File(path);
if (!file.exists())
throw new DatabaseLoadFailedException("Файл %s не был найден. Поменяйте значение переменной окружения LAB5_PATH", path);
if (!file.canRead())
throw new DatabaseLoadFailedException("У вас нет прав на чтение файла %s", path);
if (!file.canWrite())
throw new DatabaseLoadFailedException("У вас нет прав на запись в файл %s", path);
if (file.isFile())
System.out.println("Файл успешно найден");
else
file = createFile(file);
if (!file.exists()) {
errorMessage = String.format("Файл %s не был найден. Поменяйте значение переменной окружения LAB5_PATH", path);
throw new DatabaseLoadFailedException(errorMessage);
}
if (file.isDirectory())
file = createFile(file);
if (!file.canRead()) {
errorMessage = String.format("У вас нет прав на чтение файла %s", path);
throw new DatabaseLoadFailedException(errorMessage);
}
if (!file.canWrite()) {
errorMessage = String.format("У вас нет прав на запись в файл %s", path);
throw new DatabaseLoadFailedException(errorMessage);
}
this.file = file;
System.out.println("Файл успешно найден");
try {
Unmarshaller unmarshaller = context.createUnmarshaller();
@ -87,7 +101,8 @@ public class PeopleDatabase implements Database {
this.initDate = pd.initDate;
System.out.println("Инициализация успешно выполнена");
} catch (JAXBException e) {
throw new DatabaseLoadFailedException("Не удалось загрузить коллекцию из файла %s", file.getPath(), e);
e.printStackTrace();
throw new DatabaseLoadFailedException("Не удалось загрузить коллекцию из файла %s, он пуст, либо нарушена структура xml", file.getPath(), e);
}
}
@ -96,19 +111,19 @@ public class PeopleDatabase implements Database {
* переменной окружения {@link #ENV_VAR}
*
* @throws Database.DatabaseSaveFailedException если переменная окружения {@link #ENV_VAR} не задана,
* файла не существует, либо отсутствуют права на запись или чтение, или если структура xml файла
* была каким-либо образом нарушена
* файла не существует, либо отсутствуют права на запись или чтение, или если структура xml файла
* была каким-либо образом нарушена
*/
@Override
public void save() throws Database.DatabaseSaveFailedException {
if (file == null || context == null)
throw new DatabaseSaveFailedException("Не удалось сохранить коллекцию");
throw new DatabaseSaveFailedException("Не удалось сохранить коллекцию, " + errorMessage);
try {
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(this, file);
} catch (JAXBException e) {
throw new DatabaseSaveFailedException("Не удалось сохранить коллекцию в файл %s", file.getPath(), e);
throw new DatabaseSaveFailedException("Не удалось сохранить коллекцию в файл %s, формат xml файла был нарушен", file.getPath(), e);
}
}

View file

@ -6,6 +6,7 @@ import java.io.*;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Класс обработчика командной строки, реализует шаблон проектирования Singleton,
@ -19,6 +20,7 @@ public final class CommandLineHandler {
private final static CommandLineHandler instance = new CommandLineHandler();
private final Deque<Reader> inputs = new LinkedList<>();
private final Deque<String> fileNames = new LinkedList<>();
private final List<String> history = new LinkedList<>();
private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
private boolean isActive = false;
@ -128,7 +130,7 @@ public final class CommandLineHandler {
System.out.println("Что-то пошло не так");
return;
}
addNewInput(streamReader);
addNewInput(streamReader, fileName);
}
private void updateHistory(String command) {
@ -203,21 +205,19 @@ public final class CommandLineHandler {
return transform.apply(result);
}
/**
* Метод, меняющий текущий поток ввода на stream и добавляет его в очередь {@link #inputs inputs}
*
* @param reader Новый поток ввода
*/
public void addNewInput(Reader reader) {
public void addNewInput(Reader reader, String filePath) {
if (this.fileNames.contains(filePath)) {
System.err.println("Замечена рекурсия, отмена смены потока");
return;
}
this.fileNames.add(filePath);
this.reader = new BufferedReader(reader);
this.inputs.add(reader);
}
/**
* Метод, убирающий текущий поток ввода из очереди {@link #inputs inputs}
* и меняющий его либо на следующий в очереди поток, либо на System.in, если очередь пуста
*/
public void removeInput() {
if (fileNames.size() > 0)
fileNames.removeLast();
inputs.poll();
Reader reader = inputs.isEmpty() ? new InputStreamReader(System.in) : inputs.peek();
this.reader = new BufferedReader(reader);

View file

@ -113,8 +113,7 @@ public final class PeopleDatabaseCommands {
peopleDatabase.save();
System.out.println("Коллекция была успешно сохранена");
} catch (Database.DatabaseSaveFailedException e) {
e.printStackTrace();
System.out.println("Не удалось сохранить коллекцию");
System.out.println(e.getMessage());
}
}

View file

@ -45,9 +45,9 @@ public class Coordinates implements Comparable<Coordinates> {
* @throws IllegalArgumentException Если Y меньше или равен -816
*/
public void setY(float y) {
if (y <= -816)
throw new IllegalArgumentException("Поле y класса Coordinates должно быть больше -816");
this.y = y;
if (y <= -816)
this.y = 0F;
}
private double distance() {

View file

@ -1,17 +1,19 @@
package ru.erius.lab5.data;
import lombok.*;
import ru.erius.lab5.parser.NameAdapter;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Comparator;
/**
* Класс данных местоположения, реализует сортировку по умолчанию
* по имени и расстоянию до точки (0; 0; 0)
*/
@Data @NoArgsConstructor @EqualsAndHashCode @ToString
@Data @EqualsAndHashCode @ToString
@XmlAccessorType(XmlAccessType.FIELD)
public class Location implements Comparable<Location> {
@ -31,8 +33,13 @@ public class Location implements Comparable<Location> {
* Имя локации, может быть null
*/
@XmlElement(nillable = true)
@XmlJavaTypeAdapter(NameAdapter.class)
private String name;
private Location() {
this.setName(this.name);
}
/**
* Конструктор с параметрами
*
@ -59,9 +66,9 @@ public class Location implements Comparable<Location> {
* @throws IllegalArgumentException Если name является пустой строкой
*/
public void setName(String name) {
if (name != null && name.isEmpty())
throw new IllegalArgumentException("Поле name класса Location не может быть пустым");
this.name = name;
if (name != null && name.isEmpty())
this.name = null;
}
/**

View file

@ -4,7 +4,10 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
import ru.erius.lab5.parser.HeightAdapter;
import ru.erius.lab5.parser.LocalDateAdapter;
import ru.erius.lab5.parser.NameAdapter;
import ru.erius.lab5.parser.PassportAdapter;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@ -35,6 +38,7 @@ public class Person implements Comparable<Person> {
/**
* Имя человека, не может быть null, строка не может быть пустой
*/
@XmlJavaTypeAdapter(NameAdapter.class)
private String name;
/**
* Координаты человека, не может быть null
@ -49,11 +53,13 @@ public class Person implements Comparable<Person> {
* Рост человека, может быть null, значение поля должно быть больше 0
*/
@XmlElement(nillable = true)
@XmlJavaTypeAdapter(HeightAdapter.class)
private Integer height;
/**
* Номер паспорта человека, длина строки должна быть не меньше 8, поле может быть null
*/
@XmlElement(nillable = true)
@XmlJavaTypeAdapter(PassportAdapter.class)
private String passportID;
/**
* Цвет глаз человека, не может быть null
@ -132,9 +138,9 @@ public class Person implements Comparable<Person> {
* Если имя является пустой строкой
*/
public void setName(String name) {
if (name.isEmpty())
throw new IllegalArgumentException("Поле name класса Person не может быть null или пустым");
this.name = name;
if (name.isEmpty())
this.name = "none";
}
/**
@ -145,9 +151,9 @@ public class Person implements Comparable<Person> {
* @throws IllegalArgumentException Если рост меньше 0
*/
public void setHeight(Integer height) {
if (height != null && height <= 0)
throw new IllegalArgumentException("Поле height класса Person должно быть больше 0");
this.height = height;
if (height != null && height <= 0)
this.height = 150;
}
/**
@ -158,9 +164,9 @@ public class Person implements Comparable<Person> {
* @throws IllegalArgumentException Если номер паспорта меньше 8 символов в длину
*/
public void setPassportID(String passportID) {
if (passportID != null && passportID.length() < 8)
throw new IllegalArgumentException("Поле passportID класса Person не может быть меньше 8 символов в длину");
this.passportID = passportID;
if (passportID != null && passportID.length() < 8)
this.passportID = null;
}
/**

View file

@ -0,0 +1,16 @@
package ru.erius.lab5.parser;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class CoordinateYAdapter extends XmlAdapter<String, Float> {
@Override
public Float unmarshal(String v) throws Exception {
float result = Float.parseFloat(v);
return result > -816F ? result : 0F;
}
@Override
public String marshal(Float v) throws Exception {
return v.toString();
}
}

View file

@ -0,0 +1,21 @@
package ru.erius.lab5.parser;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class HeightAdapter extends XmlAdapter<String, Integer> {
@Override
public Integer unmarshal(String v) throws Exception {
if (v == null)
return null;
int result = Integer.parseInt(v);
if (result <= 0)
return 1;
return result;
}
@Override
public String marshal(Integer v) throws Exception {
return v.toString();
}
}

View file

@ -0,0 +1,15 @@
package ru.erius.lab5.parser;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class NameAdapter extends XmlAdapter<String, String> {
@Override
public String unmarshal(String v) throws Exception {
return v.isEmpty() ? "none" : v;
}
@Override
public String marshal(String v) throws Exception {
return v;
}
}

View file

@ -0,0 +1,16 @@
package ru.erius.lab5.parser;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class PassportAdapter extends XmlAdapter<String, String> {
@Override
public String unmarshal(String v) throws Exception {
return v.length() < 8 ? "no_passport" : v;
}
@Override
public String marshal(String v) throws Exception {
return v;
}
}