more xml flexibility, minor fixes

This commit is contained in:
Egor 2022-03-22 02:19:39 +03:00
parent 4f8d6b45d0
commit 51caa000f3
9 changed files with 157 additions and 66 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 KiB

After

Width:  |  Height:  |  Size: 462 KiB

View file

@ -3,7 +3,7 @@ plugins {
}
group = "ru.erius"
version = "1.1"
version = "1.2"
val mainClass = "$group.${name.toLowerCase()}.$name"
repositories {

View file

@ -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;
}
}

View file

@ -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,

View file

@ -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) {

View file

@ -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() {

View file

@ -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;
}
/**

View file

@ -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" +
"\ата создания: %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());
}
/**

View file

@ -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 {
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();
}
}
}