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 { try {
peopleDatabase.load(); peopleDatabase.load();
} catch (Database.DatabaseLoadFailedException e) { } catch (Database.DatabaseLoadFailedException e) {
System.out.println("Не удалось загрузить коллекцию из файла"); System.out.println(e.getMessage());
} }
PeopleDatabaseCommands.setPeopleDatabase(peopleDatabase); PeopleDatabaseCommands.setPeopleDatabase(peopleDatabase);

View file

@ -19,6 +19,7 @@ import java.util.TreeSet;
/** /**
* Класс базы данных людей, реализующий интерфейс Database * Класс базы данных людей, реализующий интерфейс Database
*
* @see ru.erius.lab5.collection.Database * @see ru.erius.lab5.collection.Database
*/ */
@XmlRootElement @XmlRootElement
@ -33,9 +34,14 @@ public class PeopleDatabase implements Database {
private JAXBContext context; private JAXBContext context;
@XmlTransient @XmlTransient
private File file; private File file;
@Getter @XmlElement(name = "person") @XmlTransient
private String errorMessage;
@Getter
@XmlElement(name = "person")
private TreeSet<Person> collection = new TreeSet<>(); 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(); private LocalDate initDate = LocalDate.now();
{ {
@ -50,7 +56,7 @@ public class PeopleDatabase implements Database {
return String.format("Тип коллекции: %s \n" + return String.format("Тип коллекции: %s \n" +
"Дата инициализации: %s \n" + "Дата инициализации: %s \n" +
"Количество элементов: %d \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} * переменной окружения {@link #ENV_VAR}
* *
* @throws Database.DatabaseLoadFailedException если переменная окружения {@link #ENV_VAR} не задана, * @throws Database.DatabaseLoadFailedException если переменная окружения {@link #ENV_VAR} не задана,
* файла не существует, либо отсутствуют права на запись или чтение * файла не существует, либо отсутствуют права на запись или чтение
*/ */
@Override @Override
public void load() throws Database.DatabaseLoadFailedException { public void load() throws Database.DatabaseLoadFailedException {
System.out.println("Инициализация коллекции из файла..."); System.out.println("Инициализация коллекции из файла...");
String path = System.getenv(ENV_VAR); String path = System.getenv(ENV_VAR);
if (path == null) if (path == null) {
errorMessage = "Не найдена переменная окружения LAB5_PATH";
throw new DatabaseLoadFailedException("Не найдена переменная окружения LAB5_PATH"); throw new DatabaseLoadFailedException("Не найдена переменная окружения LAB5_PATH");
file = new File(path); }
File file = new File(path);
if (!file.exists()) if (!file.exists()) {
throw new DatabaseLoadFailedException("Файл %s не был найден. Поменяйте значение переменной окружения LAB5_PATH", path); errorMessage = String.format("Файл %s не был найден. Поменяйте значение переменной окружения LAB5_PATH", path);
if (!file.canRead()) throw new DatabaseLoadFailedException(errorMessage);
throw new DatabaseLoadFailedException("У вас нет прав на чтение файла %s", path); }
if (!file.canWrite()) if (file.isDirectory())
throw new DatabaseLoadFailedException("У вас нет прав на запись в файл %s", path); file = createFile(file);
if (file.isFile()) if (!file.canRead()) {
System.out.println("Файл успешно найден"); errorMessage = String.format("У вас нет прав на чтение файла %s", path);
else throw new DatabaseLoadFailedException(errorMessage);
file = createFile(file); }
if (!file.canWrite()) {
errorMessage = String.format("У вас нет прав на запись в файл %s", path);
throw new DatabaseLoadFailedException(errorMessage);
}
this.file = file;
System.out.println("Файл успешно найден");
try { try {
Unmarshaller unmarshaller = context.createUnmarshaller(); Unmarshaller unmarshaller = context.createUnmarshaller();
@ -87,7 +101,8 @@ public class PeopleDatabase implements Database {
this.initDate = pd.initDate; this.initDate = pd.initDate;
System.out.println("Инициализация успешно выполнена"); System.out.println("Инициализация успешно выполнена");
} catch (JAXBException e) { } 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} * переменной окружения {@link #ENV_VAR}
* *
* @throws Database.DatabaseSaveFailedException если переменная окружения {@link #ENV_VAR} не задана, * @throws Database.DatabaseSaveFailedException если переменная окружения {@link #ENV_VAR} не задана,
* файла не существует, либо отсутствуют права на запись или чтение, или если структура xml файла * файла не существует, либо отсутствуют права на запись или чтение, или если структура xml файла
* была каким-либо образом нарушена * была каким-либо образом нарушена
*/ */
@Override @Override
public void save() throws Database.DatabaseSaveFailedException { public void save() throws Database.DatabaseSaveFailedException {
if (file == null || context == null) if (file == null || context == null)
throw new DatabaseSaveFailedException("Не удалось сохранить коллекцию"); throw new DatabaseSaveFailedException("Не удалось сохранить коллекцию, " + errorMessage);
try { try {
Marshaller marshaller = context.createMarshaller(); Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(this, file); marshaller.marshal(this, file);
} catch (JAXBException e) { } 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.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors;
/** /**
* Класс обработчика командной строки, реализует шаблон проектирования Singleton, * Класс обработчика командной строки, реализует шаблон проектирования Singleton,
@ -19,6 +20,7 @@ public final class CommandLineHandler {
private final static CommandLineHandler instance = new CommandLineHandler(); private final static CommandLineHandler instance = new CommandLineHandler();
private final Deque<Reader> inputs = new LinkedList<>(); private final Deque<Reader> inputs = new LinkedList<>();
private final Deque<String> fileNames = new LinkedList<>();
private final List<String> history = new LinkedList<>(); private final List<String> history = new LinkedList<>();
private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
private boolean isActive = false; private boolean isActive = false;
@ -128,7 +130,7 @@ public final class CommandLineHandler {
System.out.println("Что-то пошло не так"); System.out.println("Что-то пошло не так");
return; return;
} }
addNewInput(streamReader); addNewInput(streamReader, fileName);
} }
private void updateHistory(String command) { private void updateHistory(String command) {
@ -203,21 +205,19 @@ public final class CommandLineHandler {
return transform.apply(result); return transform.apply(result);
} }
/** public void addNewInput(Reader reader, String filePath) {
* Метод, меняющий текущий поток ввода на stream и добавляет его в очередь {@link #inputs inputs} if (this.fileNames.contains(filePath)) {
* System.err.println("Замечена рекурсия, отмена смены потока");
* @param reader Новый поток ввода return;
*/ }
public void addNewInput(Reader reader) { this.fileNames.add(filePath);
this.reader = new BufferedReader(reader); this.reader = new BufferedReader(reader);
this.inputs.add(reader); this.inputs.add(reader);
} }
/**
* Метод, убирающий текущий поток ввода из очереди {@link #inputs inputs}
* и меняющий его либо на следующий в очереди поток, либо на System.in, если очередь пуста
*/
public void removeInput() { public void removeInput() {
if (fileNames.size() > 0)
fileNames.removeLast();
inputs.poll(); inputs.poll();
Reader reader = inputs.isEmpty() ? new InputStreamReader(System.in) : inputs.peek(); Reader reader = inputs.isEmpty() ? new InputStreamReader(System.in) : inputs.peek();
this.reader = new BufferedReader(reader); this.reader = new BufferedReader(reader);

View file

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

View file

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

View file

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