more xml flexibility, minor fixes
This commit is contained in:
parent
4f8d6b45d0
commit
51caa000f3
9 changed files with 157 additions and 66 deletions
BIN
Package lab5.png
BIN
Package lab5.png
Binary file not shown.
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 462 KiB |
|
@ -3,7 +3,7 @@ plugins {
|
|||
}
|
||||
|
||||
group = "ru.erius"
|
||||
version = "1.1"
|
||||
version = "1.2"
|
||||
val mainClass = "$group.${name.toLowerCase()}.$name"
|
||||
|
||||
repositories {
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Класс базы данных людей, реализующий интерфейс Database
|
||||
|
@ -34,8 +35,6 @@ public class PeopleDatabase implements Database {
|
|||
private JAXBContext context;
|
||||
@XmlTransient
|
||||
private File file;
|
||||
@XmlTransient
|
||||
private String errorMessage;
|
||||
@Getter
|
||||
@XmlElement(name = "person")
|
||||
private TreeSet<Person> collection = new TreeSet<>();
|
||||
|
@ -85,14 +84,10 @@ public class PeopleDatabase implements Database {
|
|||
}
|
||||
if (file.isDirectory())
|
||||
file = createFile(file);
|
||||
if (!file.canRead()) {
|
||||
errorMessage = String.format("У вас нет прав на чтение файла %s", file.getAbsolutePath());
|
||||
throw new DatabaseLoadFailedException(errorMessage);
|
||||
}
|
||||
if (!file.canWrite()) {
|
||||
errorMessage = String.format("У вас нет прав на запись в файл %s", file.getAbsolutePath());
|
||||
throw new DatabaseLoadFailedException(errorMessage);
|
||||
}
|
||||
if (!file.canRead())
|
||||
throw new DatabaseLoadFailedException("У вас нет прав на чтение файла %s", file.getAbsolutePath());
|
||||
if (!file.canWrite())
|
||||
throw new DatabaseLoadFailedException("У вас нет прав на запись в файл %s", file.getAbsolutePath());
|
||||
this.file = file;
|
||||
|
||||
try {
|
||||
|
@ -117,15 +112,13 @@ public class PeopleDatabase implements Database {
|
|||
@Override
|
||||
public void save() throws Database.DatabaseSaveFailedException {
|
||||
if (!file.exists()) {
|
||||
System.out.println("Файла " + file.getAbsolutePath() + " не существует, ");
|
||||
boolean created;
|
||||
System.out.println("Файла " + file.getAbsolutePath() + " не существует, возможно он был удален, пытаюсь воссоздать файл...");
|
||||
try {
|
||||
created = file.createNewFile();
|
||||
file.createNewFile();
|
||||
System.out.println("Файл был успешно создан");
|
||||
} catch (IOException e) {
|
||||
|
||||
throw new DatabaseSaveFailedException("Не удается создать файл заново, пожалуйста, сделайте это вручную и попробуйте еще раз");
|
||||
}
|
||||
errorMessage = "Файла %s не существует, возможно он был удален";
|
||||
throw new DatabaseSaveFailedException(errorMessage, file.getAbsolutePath());
|
||||
}
|
||||
try {
|
||||
Marshaller marshaller = context.createMarshaller();
|
||||
|
@ -154,9 +147,9 @@ public class PeopleDatabase implements Database {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("PeopleDatabase(\n");
|
||||
this.collection.forEach(p -> sb.append("\t").append(p).append("\n"));
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
String result = "PeopleDatabase(";
|
||||
result += this.collection.stream().map(Person::toString).collect(Collectors.joining(", "));
|
||||
result += ")";
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import java.io.*;
|
|||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Класс обработчика командной строки, реализует шаблон проектирования Singleton,
|
||||
|
|
|
@ -66,7 +66,8 @@ public final class PeopleDatabaseCommands {
|
|||
}
|
||||
|
||||
public static void show(PeopleDatabase peopleDatabase) {
|
||||
System.out.println(peopleDatabase);
|
||||
System.out.println("Элементы коллекции:\n");
|
||||
peopleDatabase.getCollection().forEach(p -> System.out.println(p.formatted()));
|
||||
}
|
||||
|
||||
public static void add(PeopleDatabase peopleDatabase) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|||
/**
|
||||
* Класс данных координат
|
||||
*/
|
||||
@Data @NoArgsConstructor @EqualsAndHashCode @ToString
|
||||
@Data @EqualsAndHashCode @ToString
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class Coordinates implements Comparable<Coordinates> {
|
||||
|
||||
|
@ -24,13 +24,16 @@ public class Coordinates implements Comparable<Coordinates> {
|
|||
@XmlJavaTypeAdapter(Adapters.CoordinateYAdapter.class)
|
||||
private Float y;
|
||||
|
||||
private Coordinates() {
|
||||
this.x = Adapters.DEFAULT_COORDINATE;
|
||||
this.y = (float) Adapters.DEFAULT_COORDINATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Конструктор с параметрами
|
||||
*
|
||||
* @param x Координата X
|
||||
* @param y Координата Y
|
||||
*
|
||||
* @throws IllegalArgumentException Если Y меньше или равен -816
|
||||
*/
|
||||
public Coordinates(float x, float y) {
|
||||
this.x = x;
|
||||
|
@ -41,13 +44,11 @@ public class Coordinates implements Comparable<Coordinates> {
|
|||
* Сеттер для поля y
|
||||
*
|
||||
* @param y Координата Y
|
||||
*
|
||||
* @throws IllegalArgumentException Если Y меньше или равен -816
|
||||
*/
|
||||
public void setY(float y) {
|
||||
this.y = y;
|
||||
if (y <= -816)
|
||||
this.y = 0F;
|
||||
this.y = (float) Adapters.DEFAULT_COORDINATE;
|
||||
}
|
||||
|
||||
private double distance() {
|
||||
|
|
|
@ -6,7 +6,6 @@ import ru.erius.lab5.parser.Adapters;
|
|||
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;
|
||||
|
||||
/**
|
||||
|
@ -16,7 +15,6 @@ import java.util.Comparator;
|
|||
@Data @EqualsAndHashCode @ToString
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class Location implements Comparable<Location> {
|
||||
|
||||
/**
|
||||
* Координата X типа double
|
||||
*/
|
||||
|
@ -26,18 +24,20 @@ public class Location implements Comparable<Location> {
|
|||
*/
|
||||
private float y;
|
||||
/**
|
||||
* Координата Z типа Long, не может быть null
|
||||
* Координата Z типа long, не может быть null
|
||||
*/
|
||||
private Long z;
|
||||
private long z;
|
||||
/**
|
||||
* Имя локации, может быть null
|
||||
*/
|
||||
@XmlElement(nillable = true)
|
||||
@XmlJavaTypeAdapter(Adapters.NameAdapter.class)
|
||||
private String name;
|
||||
|
||||
private Location() {
|
||||
this.setName(this.name);
|
||||
this.x = Adapters.DEFAULT_COORDINATE;
|
||||
this.y = Adapters.DEFAULT_COORDINATE;
|
||||
this.z = Adapters.DEFAULT_COORDINATE;
|
||||
this.name = Adapters.DEFAULT_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,11 +48,9 @@ public class Location implements Comparable<Location> {
|
|||
* @param z Координата Z
|
||||
* @param name Имя локации
|
||||
*
|
||||
* @throws IllegalArgumentException будет брошено, если name является пустой строкой
|
||||
*
|
||||
* @throws NullPointerException будет брошено в случае, если Z является null
|
||||
*/
|
||||
public Location(double x, float y, @NonNull Long z, String name) {
|
||||
public Location(double x, float y, long z, String name) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
|
@ -62,13 +60,11 @@ public class Location implements Comparable<Location> {
|
|||
/**
|
||||
* Сеттер для поля name
|
||||
* @param name Имя локации
|
||||
*
|
||||
* @throws IllegalArgumentException Если name является пустой строкой
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
if (name != null && name.isEmpty())
|
||||
this.name = null;
|
||||
this.name = Adapters.DEFAULT_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -60,10 +60,12 @@ public class Person implements Comparable<Person> {
|
|||
/**
|
||||
* Цвет глаз человека, не может быть null
|
||||
*/
|
||||
@XmlJavaTypeAdapter(Adapters.ColorAdapter.class)
|
||||
private Color eyeColor;
|
||||
/**
|
||||
* Национальность человека, не может быть null
|
||||
*/
|
||||
@XmlJavaTypeAdapter(Adapters.CountryAdapter.class)
|
||||
private Country nationality;
|
||||
/**
|
||||
* Местоположение человека, может быть null
|
||||
|
@ -75,6 +77,14 @@ public class Person implements Comparable<Person> {
|
|||
*/
|
||||
private Person() {
|
||||
this.id = ++existingPeople;
|
||||
this.creationDate = Adapters.DEFAULT_DATE;
|
||||
this.name = Adapters.DEFAULT_NAME;
|
||||
this.coordinates = Adapters.DEFAULT_COORDINATES;
|
||||
this.height = Adapters.DEFAULT_HEIGHT;
|
||||
this.passportID = Adapters.DEFAULT_PASSPORT;
|
||||
this.eyeColor = Adapters.DEFAULT_COLOR;
|
||||
this.nationality = Adapters.DEFAULT_COUNTRY;
|
||||
this.location = Adapters.DEFAULT_LOCATION;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,14 +98,9 @@ public class Person implements Comparable<Person> {
|
|||
* @param nationality Национальность человека
|
||||
* @param location Местоположение человека
|
||||
*
|
||||
* @throws IllegalArgumentException Если:
|
||||
* name является пустой строкой,
|
||||
* height меньше 0,
|
||||
* Длина passportID меньше 8 символов
|
||||
*
|
||||
* @throws NullPointerException Если coordinates, eyeColor или nationality являются null
|
||||
* @throws NullPointerException Если name, coordinates, eyeColor или nationality являются null
|
||||
*/
|
||||
public Person(String name, @NonNull Coordinates coordinates, Integer height, String passportID,
|
||||
public Person(@NonNull String name, @NonNull Coordinates coordinates, Integer height, String passportID,
|
||||
@NonNull Color eyeColor, @NonNull Country nationality, Location location) {
|
||||
this.id = ++existingPeople;
|
||||
this.creationDate = LocalDate.now();
|
||||
|
@ -129,40 +134,54 @@ public class Person implements Comparable<Person> {
|
|||
*
|
||||
* @param name
|
||||
* Имя человека
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* Если имя является пустой строкой
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
if (name.isEmpty())
|
||||
this.name = "none";
|
||||
this.name = Adapters.DEFAULT_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сеттер для поля height
|
||||
*
|
||||
* @param height Рост человека
|
||||
*
|
||||
* @throws IllegalArgumentException Если рост меньше 0
|
||||
*/
|
||||
public void setHeight(Integer height) {
|
||||
this.height = height;
|
||||
if (height != null && height <= 0)
|
||||
this.height = 150;
|
||||
this.height = Adapters.DEFAULT_HEIGHT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сеттер для поля passportID
|
||||
*
|
||||
* @param passportID Номер паспорта человека
|
||||
*
|
||||
* @throws IllegalArgumentException Если номер паспорта меньше 8 символов в длину
|
||||
*/
|
||||
public void setPassportID(String passportID) {
|
||||
this.passportID = passportID;
|
||||
if (passportID != null && passportID.length() < 8)
|
||||
this.passportID = null;
|
||||
this.passportID = Adapters.DEFAULT_PASSPORT;
|
||||
}
|
||||
|
||||
public String formatted() {
|
||||
return String.format("Человек %s:\n" +
|
||||
"\tИмя: %s\n" +
|
||||
"\tДата создания: %s\n" +
|
||||
"\tРост: %s\n" +
|
||||
"\tНомер паспорта: %s\n" +
|
||||
"\tЦвет глаз: %s\n" +
|
||||
"\tНациональность: %s\n" +
|
||||
"\tМестоположение:\n" +
|
||||
"\t\tНазвание: %s\n" +
|
||||
"\t\tX: %s\n" +
|
||||
"\t\tY: %s\n" +
|
||||
"\t\tZ: %s\n" +
|
||||
"\tКоординаты:\n" +
|
||||
"\t\tX: %s\n" +
|
||||
"\t\tY: %s\n",
|
||||
id, name, creationDate, height, passportID, eyeColor, nationality,
|
||||
location.getName(), location.getX(), location.getY(), location.getZ(),
|
||||
coordinates.getX(), coordinates.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,15 +1,39 @@
|
|||
package ru.erius.lab5.parser;
|
||||
|
||||
import ru.erius.lab5.data.Color;
|
||||
import ru.erius.lab5.data.Coordinates;
|
||||
import ru.erius.lab5.data.Country;
|
||||
import ru.erius.lab5.data.Location;
|
||||
import ru.erius.lab5.util.UtilFunctions;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class Adapters {
|
||||
|
||||
public final static LocalDate DEFAULT_DATE = LocalDate.of(1970, 1, 1);
|
||||
public final static int DEFAULT_HEIGHT = 150;
|
||||
public final static Color DEFAULT_COLOR = Color.BLACK;
|
||||
public final static Country DEFAULT_COUNTRY = Country.UNITED_KINGDOM;
|
||||
public final static String DEFAULT_NAME = "name",
|
||||
DEFAULT_PASSPORT = "passport";
|
||||
public final static int DEFAULT_COORDINATE = 0;
|
||||
public final static Coordinates DEFAULT_COORDINATES = new Coordinates(DEFAULT_COORDINATE, DEFAULT_COORDINATE);
|
||||
public final static Location DEFAULT_LOCATION = new Location(DEFAULT_COORDINATE, DEFAULT_COORDINATE, DEFAULT_COORDINATE, DEFAULT_NAME);
|
||||
|
||||
public static class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
|
||||
@Override
|
||||
public LocalDate unmarshal(String v) throws Exception {
|
||||
return LocalDate.parse(v);
|
||||
try {
|
||||
return LocalDate.parse(v);
|
||||
} catch (DateTimeParseException e) {
|
||||
System.err.printf("Не удалось преобразовать %s в тип LocalDate, используем значение по умолчанию %s\n", v, DEFAULT_DATE);
|
||||
return DEFAULT_DATE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,8 +45,17 @@ public final class Adapters {
|
|||
public static class CoordinateYAdapter extends XmlAdapter<String, Float> {
|
||||
@Override
|
||||
public Float unmarshal(String v) throws Exception {
|
||||
float result = Float.parseFloat(v);
|
||||
return result > -816F ? result : 0F;
|
||||
float result;
|
||||
try {
|
||||
result = Float.parseFloat(v);
|
||||
} catch (NumberFormatException e) {
|
||||
return (float) DEFAULT_COORDINATE;
|
||||
}
|
||||
if (result <= -816F) {
|
||||
System.err.printf("Координата Y %s не может быть меньше или равна -816, используем значение по умолчанию %s\n", v, DEFAULT_COORDINATE);
|
||||
return (float) DEFAULT_COORDINATE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -36,9 +69,16 @@ public final class Adapters {
|
|||
public Integer unmarshal(String v) throws Exception {
|
||||
if (v == null)
|
||||
return null;
|
||||
int result = Integer.parseInt(v);
|
||||
if (result <= 0)
|
||||
return 1;
|
||||
int result;
|
||||
try {
|
||||
result = Integer.parseInt(v);
|
||||
} catch (NumberFormatException e) {
|
||||
return DEFAULT_HEIGHT;
|
||||
}
|
||||
if (result <= 0) {
|
||||
System.err.printf("Рост %s не может быть меньше или равен 0, используем значение по умолчанию %s\n", v, DEFAULT_HEIGHT);
|
||||
return DEFAULT_HEIGHT;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -51,7 +91,11 @@ public final class Adapters {
|
|||
public static class NameAdapter extends XmlAdapter<String, String> {
|
||||
@Override
|
||||
public String unmarshal(String v) throws Exception {
|
||||
return v.isEmpty() ? "none" : v;
|
||||
if (v.isEmpty()) {
|
||||
System.err.printf("Имя не может быть пустым, используем значение по умолчанию %s\n", DEFAULT_NAME);
|
||||
return DEFAULT_NAME;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,7 +107,11 @@ public final class Adapters {
|
|||
public static class PassportAdapter extends XmlAdapter<String, String> {
|
||||
@Override
|
||||
public String unmarshal(String v) throws Exception {
|
||||
return v.length() < 8 ? "no_passport" : v;
|
||||
if (v.length() < 8) {
|
||||
System.err.printf("Номер паспорта %s должен быть как минимум 8 символов в длину, используем значение по умолчанию %s\n", v, DEFAULT_PASSPORT);
|
||||
return DEFAULT_PASSPORT;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,4 +119,38 @@ public final class Adapters {
|
|||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ColorAdapter extends XmlAdapter<String, Color> {
|
||||
@Override
|
||||
public Color unmarshal(String v) throws Exception {
|
||||
Color color = UtilFunctions.enumOrNull(v.toUpperCase(Locale.ROOT), Color.class);
|
||||
if (color == null) {
|
||||
System.err.printf("Цвет глаз %s не соответствует одному из этих вариантов - %s, используем значение по умолчанию %s\n", v, Arrays.toString(Color.values()), DEFAULT_COLOR);
|
||||
return DEFAULT_COLOR;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String marshal(Color v) throws Exception {
|
||||
return v.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class CountryAdapter extends XmlAdapter<String, Country> {
|
||||
@Override
|
||||
public Country unmarshal(String v) throws Exception {
|
||||
Country country = UtilFunctions.enumOrNull(v.toUpperCase(Locale.ROOT), Country.class);
|
||||
if (country == null) {
|
||||
System.err.printf("Национальность %s не соответствует одному из этих вариантов - %s, используем значение по умолчанию %s\n", v, Arrays.toString(Country.values()), DEFAULT_COUNTRY);
|
||||
return DEFAULT_COUNTRY;
|
||||
}
|
||||
return country;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String marshal(Country v) throws Exception {
|
||||
return v.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue