diff --git a/README.md b/README.md index 653fc8d..06548dd 100644 --- a/README.md +++ b/README.md @@ -14,235 +14,21 @@ A library with common Java types that are mostly immutable value objects. - 0.7.x = **Java 11** before namespace change from 'javax' to 'jakarta' - 0.6.9 (or previous) = **Java 8** - # Features - -## Package "common" -Base classes like utilities and general annotations. - -* [FileExists Validator](#fileexists-validator) -* [IsDirectory Validator](#isdirectory-validator) -* [TraceStringCapable](#tracestringcapable) - -## Package "ui" -Annotations that can be placed on plain objects but may be used by a user interface to render that object in some way. - -* [Label annotation](#label-annotation) -* [Prompt annotation](#prompt-annotation) -* [ShortLabel annotation](#shortlabel-annotation) -* [TableColumn annotation](#tablecolumn-annotation) -* [TextField annotation](#textfield-annotation) -* [Tooltip annotation](#tooltip-annotation) - -## Package "vo" -Provides Value Objects and utility classes for those immutable objects. - -[Click here for details...](#description-vo) +- [Common](common) - Interfaces, annotations and validators. +- [Core](core) - Value objects and utility classes for these value objects. +- [Jackson](jackson) - FasterXML Jackson serializer/deserializer for the types defined in [Core](core). +- [JAX-B](jaxb) - Jakarta XML Binding (JAX-B) XML adapters for the types defined in [Core](core). +- [JPA](jpa) - Jakarta Persistence API (JPA) attribute converters for the types defined in [Core](core). +- [JSON-B](jsonb) - Jakarta JSON Binding (JSON-B) adapters for the types defined in [Core](../core). +- [JUnit](junit) - Defines ArchUnit conditions for classes using this library. +- [UI](ui) - Annotations that can be placed on plain objects but may be used by a user interface to render that object in some way. * * * -## Description "common" -Base classes like utilities and general annotations. - -### FileExists Validator -Verifies that the file exists (Bean validation JSR 303). -```Java -@FileExists -private File myFile; -``` - -### IsDirectory Validator -Verifies that it's a directory and not a file (Bean validation JSR 303). -```Java -@IsDirectory -private File myDir; -``` - -### TraceStringCapable -Marker interface for classes that provide a special representation for trace output. -```Java -public class MyClass implements TraceStringCapable { - - @Override - public String toTraceString() { - return "A long and very detailed instance description for trace output"; - } - -} -``` - -## Description "ui" -The annotations may be used by UI elements to display an appropriate text for a type or a field. -You can also configure a bundle and key for internationalization. - -### Label annotation -Use this annotation to assign a label to a class or an attribute. -```Java -@Label(value = "Birthday", bundle = "my/MyBundle", key = "birthday.label") -private Date birthday; -``` - -### Prompt annotation -Use this annotation to assign a prompt (example value) to a class or an attribute. -```Java -@Prompt(value = "12-31-1993", bundle = "my/MyBundle", key = "birthday.prompt") -private Date birthday; -``` - -### ShortLabel annotation -Use this annotation to assign an abbreviation to a class or an attribute. -```Java -@ShortLabel(value = "BD", bundle = "my/MyBundle", key = "birthday.short") -private Date birthday; -``` - -### TableColumn annotation -Use this annotation to assign preferred table column values to a field. -```Java -@TableColumn(pos = 3, width = 20, unit= FontSizeUnit.EM, getter = "isInternal") -private boolean permanentEmployee; -``` - -### TextField annotation -Use this annotation to express the annotated attribute should be rendered as a text field. -User agents are expected to use this information as hint for the rendering process. -```Java -@TextField(width = 50) -private String lastName; -``` - -### Tooltip annotation -Use this annotation to assign a tooltip to a class or a field. -```Java -@Tooltip(value = "The person's birthday", bundle = "my/MyBundle", key = "birthday.tooltip") -private Date birthday; -``` - -### AnnotationAnalyzer -You can use [AnnotationAnalyzer](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/AnnotationAnalyzer.java) to read the internationalized text from above annotations. - -Read a single ```@Label``` text: -```Java -AnnotationAnalyzer analyzer = new AnnotationAnalyzer(); - -Field field = MyClass.class.getDeclaredField("birthday"); - -FieldTextInfo labelInfoGermany = analyzer.createFieldInfo(field, Locale.GERMANY, Label.class); -System.out.println(labelInfoGermany.getText()); -// Prints "Geburtstag" - -FieldTextInfo labelInfoUs = analyzer.createFieldInfo(field, Locale.US, Label.class); -System.out.println(labelInfoUs.getText()); -// Prints "Birthday" -``` - -Read all ```@Label``` texts from a class: -```Java -AnnotationAnalyzer analyzer = new AnnotationAnalyzer(); -List infos = analyzer.createFieldInfos(MyClass.class, Locale.US, Label.class); -for (final FieldTextInfo info : infos) { - // Text of the label or the name of the field if the text is null - System.out.println(info.getTextOrField()); -} -``` - -Create a list of [TableColumnInfo](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/TableColumnInfo.java) -that combines [@Label](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/Label.java), -[@ShortLabel](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/ShortLabel.java) and -[@TableColumn](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/TableColumn.java) annotations. -```Java -List columns = TableColumnInfo.create(MyClass.class, Locale.US); -for (TableColumnInfo column : columns) { - System.out.println(column.getText()); -} -``` - -This allows easy creation of a table model for example for JavaFX: -```Java -TableView tableView = new TableView<>(); -List tableCols = TableColumnInfo.create(MyClass.class, Locale.getDefault()); -Collections.sort(tableCols); -for (TableColumnInfo column : tableCols) { - TableColumn tc = new TableColumn<>(); - tc.setStyle("-fx-alignment: CENTER;"); - Label label = new Label(column.getShortText()); - label.setTooltip(new Tooltip(column.getTooltip())); - tc.setGraphic(label); - tc.setCellValueFactory(new PropertyValueFactory(column.getField().getName())); - tc.setPrefWidth(column.getWidth().getSize()); - tableView.getColumns().add(tc); -} -``` - -### Examples annotation -Use this annotation to assign some example values to a class or an attribute. -```Java -@Examples({"John", "Jane"}) -private String firstName; -``` - -### Mappings annotation -Use this annotation to assign key/value mappings to a class or an attribute. -```Java -@Mappings({"1=One", "2=Two", "3=Three"}) -private String code; -``` - -## Description "vo" -Provides Value Objects (immutable objects) that represents an object whose equality isn't based on identity. -That means instances of this type are equal when they have the same value, not necessarily being the same object. -Additionally some helper classes (like validators) are placed in this package. - -**Interfaces** -* [ValueObject](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/ValueObject.java) - Tag interface for value objects. -* [ValueObjectConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/ValueObjectConverter.java) - Converts a value object into it's base type and back. -* [ValueObjectWithBaseType](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/ValueObjectWithBaseType.java) - Value object that may be expressed in a more general type with relaxed restrictions. Often basic Java types like String or numeric values (Long, Integer, ...) are used for this. -* [ValueOfCapable](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/ValueOfCapable.java) - Classes that can convert a string into a type (They have a ```valueOf(String)``` method). -* [AsStringCapable](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/AsStringCapable.java) - Classes that provides a string representation (They have a ```asString()``` method). - -**Base classes** that allow an easy implementation of concrete classes. -* [AbstractIntegerValueObject](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/AbstractIntegerValueObject.java) - A value object that is based on an integer. -* [AbstractLongValueObject](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/AbstractLongValueObject.java) - A value object that is based on a long. -* [AbstractStringValueObject](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/AbstractStringValueObject.java) - A value object that is based on a string. -* [AbstractUuidValueObject](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/AbstractUuidValueObject.java) - A value object that is based on a UUID. -* [AbstractValueObjectConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/AbstractValueObjectConverter.java) - Converts value objects. It combines a JAXB [XmlAdapter](https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html), JPA [AttributeConverter](https://docs.oracle.com/javaee/7/api/javax/persistence/AttributeConverter.html) and [ValueObjectConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/ValueObjectConverter.java). - -**Predefined Value Objects** -* [CurrencyAmount](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/CurrencyAmount.java) - Combines a currency (like "USD" or "EUR") with a big decimal value (like "**512 EUR**"). There is also a [CurrencyAmountConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/CurrencyAmountConverter.java) (JAX-B, JSON-B and JPA) and a [CurrencyAmountValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/CurrencyAmountValidator.java) (```@CurrencyAmountStr```) available. -* [EmailAddress](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/EmailAddress.java) - Email address. There is also a [EmailAddressConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/EmailAddressConverter.java) (JAX-B, JSON-B and JPA) and a [EmailAddressValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/EmailAddressValidator.java) (```@EmailAddressStr```) available. -* [Password](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/Password.java) - A password with a length between 8 and 20 characters. There is also a [PasswordConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/PasswordConverter.java) (JAX-B, JSON-B and JPA) and a [PasswordValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/PasswordValidator.java) (```@PasswordStr```) available. -* [PasswordSha512](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/PasswordSha512.java) - A SHA-512 hashed password that is HEX encoded. There is also a [PasswordSha512Converter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/PasswordSha512Converter.java) (JAX-B, JSON-B and JPA) and a [PasswordSha512Validator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/PasswordSha512Validator.java) (```@PasswordSha512Str```) available. -* [UserName](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/UserName.java) - User name with restricted character set and length. There is also a [UserNameConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/UserNameConverter.java) (JAX-B, JSON-B and JPA) and a [UserNameValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/UserNameValidator.java) (```@UserNameStr```) available. -* [Hour](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/Hour.java) - Hour of a day like '**23:59**' (24 hours, sometimes called Military Time). There is also an [HourConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/HourConverter.java) (JAX-B, JSON-B and JPA) and an [HourStrValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/HourStrValidator.java) (```@HourStr```) available. -* [HourRange](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/HourRange.java) - Range of hours of a day like '**00:00-24:00**' (24 hours, sometimes called Military Time). There is also an [HourRangeConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/HourRangeConverter.java) (JAX-B, JSON-B and JPA) and an [HourRangeStrValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/HourRangeStrValidator.java) (```@HourRangeStr```) available. -* [HourRanges](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/HourRanges.java) - Multiple range of hours of a day like '**09:00-12:00+13:00-17:00**'. There is also an [HourRangesConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/HourRangesConverter.java) (JAX-B, JSON-B and JPA) and an [HourRangesStrValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/HourRangesStrValidator.java) (```@HourRangesStr```) available. -* [DayOfTheWeek](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/DayOfTheWeek.java) - The days of the week '**Mon**'-'**Sun**'(from Monday to Sunday) plus '**PH**' (Public Holiday). There is also an [DayOfTheWeekConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/DayOfTheWeekConverter.java) (JAX-B, JSON-B and JPA) and an [DayOfTheWeekStrValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/DayOfTheWeekStrValidator.java) (```@DayOfTheWeekStr```) available. -* [MultiDayOfTheWeek](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/MultiDayOfTheWeek.java) - Multiple days of the week like '**Mon/Tue/Wed-Fri/PH**' (Monday AND Tuesday AND Wednesday TO Friday AND Public Holidays). There is also an [MultiDayOfTheWeekConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/MultiDayOfTheWeekConverter.java) (JAX-B, JSON-B and JPA) and an [MultiDayOfTheWeekStrValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/MultiDayOfTheWeekStrValidator.java) (```@MultiDayOfTheWeekStr```) available. -* [DayOpeningHours](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/DayOpeningHours.java) - Multiple range of hours of single a day like '**Mon 09:00-12:00+13:00-17:00**'. There is also an [DayOpeningHoursConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/DayOpeningHoursConverter.java) (JAX-B, JSON-B and JPA) and an [DayOpeningHoursStrValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/DayOpeningHoursStrValidator.java) (```@DayOpeningHoursStr```) available. -* [WeeklyOpeningHours](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/WeeklyOpeningHours.java) - weekly opening hours separated by a comma like '**Mon-Fri 09:00-12:00+13:00-17:00,Sat/Sun 09:-12:00**'. There is also an [WeeklyOpeningHoursConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/WeeklyOpeningHoursConverter.java) (JAX-B, JSON-B and JPA) and an [WeeklyOpeningHoursStrValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/WeeklyOpeningHoursStrValidator.java) (```@WeeklyOpeningHoursStr```) available. - -**Validators** -* [DateValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/DateValidator.java) - Validates that a string is a date using the current locale ([@DateStr](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/DateStr.java)). -* [LocaleValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/LocaleValidator.java) - Validates that a string is a valid locale ([@LocaleStr](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/LocaleStr.java)). There is also a [LocaleConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/LocaleConverter.java) available. -* [PropertiesContainValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/PropertiesContainValidator.java) - Validates that a string is one out of a list of constants ([@PropertiesContain("one", "two", "three")](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/PropertiesContain.java)). -* [TrimmedNotEmptyValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/TrimmedNotEmptyValidator.java) - Validates that a string is not empty after it was trimmed [@TrimmedNotEmpty](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/TrimmedNotEmpty.java) -* [UUIDValidator](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/UUIDValidator.java) - Validates that a string is a valid UUID ([@UUIDStr](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/UUIDStr.java)). There is also a [UUIDConverter](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/UUIDConverter.java) available. - -**Other** -* [KeyValue](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/vo/KeyValue.java) - Container for a key (String) and a value (Object). - -* * * - -# Changes - -### 0.7.0-SNAPSHOT -This version has several incompatible changes because of moving it to Java 11. -- Removed JaxbMarshallable classes because of illegal reflective access - - ### Snapshots -Snapshots can be found on the [OSS Sonatype Snapshots Repository](http://oss.sonatype.org/content/repositories/snapshots/org/fuin "Snapshot Repository"). +Snapshots can be found on the [OSS Sonatype Snapshots Repository](https://oss.sonatype.org/index.html#view-repositories;snapshots~browsestorage~/org/fuin "Snapshot Repository"). Add the following to your .m2/settings.xml to enable snapshots in your Maven build: diff --git a/common/README.md b/common/README.md new file mode 100644 index 0000000..7f7ecf0 --- /dev/null +++ b/common/README.md @@ -0,0 +1,113 @@ +# objects4j-common +Some interfaces, annotations and validators. + +## Bean validation (JSR 303) +Constraint annotations and the corresponding validators. + +### [@IsFile](src/main/java/org/fuin/objects4j/common/IsFile.java) +Verifies that the annotated java File is a file and not a directory +```Java +@IsFile +private File myDir; +``` + +### [@FileExists](src/main/java/org/fuin/objects4j/common/FileExists.java) +Verifies that the file exists +```Java +@FileExists +private File myFile; +``` + +### [@IsDirectory](src/main/java/org/fuin/objects4j/common/IsDirectory.java) +Verifies that it's a directory and not a file +```Java +@IsDirectory +private File myDir; +``` + +### [@HasPublicStaticIsValidMethod](src/main/java/org/fuin/objects4j/common/HasPublicStaticIsValidMethod.java) / [@HasPublicStaticIsValidMethods](src/main/java/org/fuin/objects4j/common/HasPublicStaticIsValidMethods.java) +Tags a class that has a public static method that verifies if a given value can be converted into an instance of the class. +The default is a method named "isValid" with a String parameter. You can change this using the annotation arguments. +```Java +@HasPublicStaticIsValidMethod +public class IBAN { + public static boolean isValid(String ibanStr) { + ... + } +} +``` + +### [@HasPublicStaticValueOfMethod](src/main/java/org/fuin/objects4j/common/HasPublicStaticValueOfMethod.java) / [@HasPublicStaticValueOfMethods](src/main/java/org/fuin/objects4j/common/HasPublicStaticValueOfMethods.java) +Tags a class that has a public static method that converts if a given value into an instance of the class. +The default is a method named "valueOf" with a String parameter. You can change this using the annotation arguments. +```Java +@HasPublicStaticValueOfMethod +public class IBAN { + public static IBAN valueOf(String ibanStr) { + return new IBAN(ibanStr); + } +} +``` + +## Interfaces +Annotated classes provide some special functionality. + +### String methods + +#### [TraceStringCapable](src/main/java/org/fuin/objects4j/common/TraceStringCapable.java) +Marker interface for classes that provide a special representation for trace output. + +#### [AsStringCapable](src/main/java/org/fuin/objects4j/common/AsStringCapable.java) +Objects that provides a string representation of itself that is used for displaying business values. +In contrast to that is the standard "toString()" method often used for technical information. + +```Java +public class CompanyName implements TraceStringCapable, AsStringCapable { + + private String str; + + @Override + public String asString() { + return str; + } + + @Override + public String toTraceString() { + return str + "[" + this.hashCode() + "]"; + } + + @Override + public String toString() { + return "CompanyName{str=" + str + '}'; + } + +} +``` + +### [MarshalInformation](src/main/java/org/fuin/objects4j/common/MarshalInformation.java) +Tags any instance that is capable of delivering additional information for serialization/deserialization. +In contrast to XML where the element name can be used to determine the type of the object, as with JSON +there is often just an unknown type of object. This interface helps to determine the full qualified name +of the class and the tag name to use. + +### [ExceptionShortIdentifable](src/main/java/org/fuin/objects4j/common/ExceptionShortIdentifable.java) +Marks an exception that provides a unique short identifier. This identifier should be human-readable and +is meant to be displayed to an end user. A service desk can use it to identify the type of error quickly +and for example attach a guideline to it that explains how to solve the problem. + +### [ToExceptionCapable](src/main/java/org/fuin/objects4j/common/ToExceptionCapable.java) +Tags objects that can create an exception based on their data. + +### [UniquelyNumbered](src/main/java/org/fuin/objects4j/common/UniquelyNumbered.java) +Tags objects that provide a unique (long) number in their context. +This is used along with [UniquelyNumberedException](src/main/java/org/fuin/objects4j/common/UniquelyNumberedException.java) +which is a base class for exceptions that have such a unique ID. + +### [ValueObject](src/main/java/org/fuin/objects4j/common/ValueObject.java) +Immutable object that represents an object whose equality isn't based on identity. +That means instances of this type are equal when they have the same value, not necessarily being the same object. +A Java record is a perfect match for this kind of object. + +### [ValueObjectWithBaseType](src/main/java/org/fuin/objects4j/common/ValueObjectWithBaseType.java) +Value object that may be expressed in a more general type with relaxed restrictions. +Often basic Java types like String or numeric values (Long, Integer, ...) are used for this. diff --git a/core/src/main/java/org/fuin/objects4j/core/AsStringCapable.java b/common/src/main/java/org/fuin/objects4j/common/AsStringCapable.java similarity index 96% rename from core/src/main/java/org/fuin/objects4j/core/AsStringCapable.java rename to common/src/main/java/org/fuin/objects4j/common/AsStringCapable.java index 2e2a9d0..e5533a5 100644 --- a/core/src/main/java/org/fuin/objects4j/core/AsStringCapable.java +++ b/common/src/main/java/org/fuin/objects4j/common/AsStringCapable.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ -package org.fuin.objects4j.core; +package org.fuin.objects4j.common; /** * Provides a string representation of itself. diff --git a/common/src/main/java/org/fuin/objects4j/common/ExceptionShortIdentifable.java b/common/src/main/java/org/fuin/objects4j/common/ExceptionShortIdentifable.java index 640bc2a..8e6fc3b 100644 --- a/common/src/main/java/org/fuin/objects4j/common/ExceptionShortIdentifable.java +++ b/common/src/main/java/org/fuin/objects4j/common/ExceptionShortIdentifable.java @@ -18,7 +18,7 @@ package org.fuin.objects4j.common; /** - * Marks an exception that provides a unique short identifier. This identifier should be human readable and is meant to be displayed to an + * Marks an exception that provides a unique short identifier. This identifier should be human-readable and is meant to be displayed to an * end user. A service desk can use it to identify the type of error quickly and for example attach a guideline to it that explains how to * solve the problem. */ diff --git a/common/src/main/java/org/fuin/objects4j/common/MarshalInformation.java b/common/src/main/java/org/fuin/objects4j/common/MarshalInformation.java index d56bfab..dde9a32 100644 --- a/common/src/main/java/org/fuin/objects4j/common/MarshalInformation.java +++ b/common/src/main/java/org/fuin/objects4j/common/MarshalInformation.java @@ -18,9 +18,9 @@ package org.fuin.objects4j.common; /** - * Tags any instance that is capable of delivering additional informations for serialization/deserialization. In contrast to XML where the + * Tags any instance that is capable of delivering additional information for serialization/deserialization. In contrast to XML where the * element name can be used to determine the type of the object, as with JSON there is often just an unknown type of object. This class - * helps determining the full qualified name of the class and the tag name to use. + * helps to determine the full qualified name of the class and the tag name to use. * * @param * Type of data returned. diff --git a/core/src/main/java/org/fuin/objects4j/core/ValueObject.java b/common/src/main/java/org/fuin/objects4j/common/ValueObject.java similarity index 83% rename from core/src/main/java/org/fuin/objects4j/core/ValueObject.java rename to common/src/main/java/org/fuin/objects4j/common/ValueObject.java index 94aee36..97352e3 100644 --- a/core/src/main/java/org/fuin/objects4j/core/ValueObject.java +++ b/common/src/main/java/org/fuin/objects4j/common/ValueObject.java @@ -15,11 +15,11 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ -package org.fuin.objects4j.core; +package org.fuin.objects4j.common; /** - * Immutable object that represents an object whose equality isn't based on identity. That means instances of this type are equal when they - * have the same value, not necessarily being the same object. + * Immutable object that represents an object whose equality isn't based on identity. + * That means instances of this type are equal when they have the same value, not necessarily being the same object. */ public interface ValueObject { diff --git a/core/src/main/java/org/fuin/objects4j/core/ValueObjectConverter.java b/common/src/main/java/org/fuin/objects4j/common/ValueObjectConverter.java similarity index 96% rename from core/src/main/java/org/fuin/objects4j/core/ValueObjectConverter.java rename to common/src/main/java/org/fuin/objects4j/common/ValueObjectConverter.java index 3919b4a..0532030 100644 --- a/core/src/main/java/org/fuin/objects4j/core/ValueObjectConverter.java +++ b/common/src/main/java/org/fuin/objects4j/common/ValueObjectConverter.java @@ -15,7 +15,9 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ -package org.fuin.objects4j.core; +package org.fuin.objects4j.common; + +import org.fuin.objects4j.common.ValueObjectWithBaseType; /** * Converts a value object into it's base type and back. diff --git a/core/src/main/java/org/fuin/objects4j/core/ValueObjectWithBaseType.java b/common/src/main/java/org/fuin/objects4j/common/ValueObjectWithBaseType.java similarity index 90% rename from core/src/main/java/org/fuin/objects4j/core/ValueObjectWithBaseType.java rename to common/src/main/java/org/fuin/objects4j/common/ValueObjectWithBaseType.java index 3f349fb..d5b605b 100644 --- a/core/src/main/java/org/fuin/objects4j/core/ValueObjectWithBaseType.java +++ b/common/src/main/java/org/fuin/objects4j/common/ValueObjectWithBaseType.java @@ -15,13 +15,13 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ -package org.fuin.objects4j.core; +package org.fuin.objects4j.common; import jakarta.validation.constraints.NotNull; /** - * Value object that may be expressed in a more general type with relaxed restrictions. Often basic Java types like String or numeric values - * (Long, Integer, ...) are used for this. + * Value object that may be expressed in a more general type with relaxed restrictions. + * Often basic Java types like String or numeric values (Long, Integer, ...) are used for this. * * @param * Base type that may represent this type of value object. diff --git a/core/src/main/java/org/fuin/objects4j/core/ValueOfCapable.java b/common/src/main/java/org/fuin/objects4j/common/ValueOfCapable.java similarity index 92% rename from core/src/main/java/org/fuin/objects4j/core/ValueOfCapable.java rename to common/src/main/java/org/fuin/objects4j/common/ValueOfCapable.java index 8e63488..2cb033e 100644 --- a/core/src/main/java/org/fuin/objects4j/core/ValueOfCapable.java +++ b/common/src/main/java/org/fuin/objects4j/common/ValueOfCapable.java @@ -15,12 +15,12 @@ * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see http://www.gnu.org/licenses/. */ -package org.fuin.objects4j.core; +package org.fuin.objects4j.common; import jakarta.annotation.Nullable; /** - * Can convert a string into a type. + * Functional interface used ton convert a string into a type. * * @param * Target type. diff --git a/common/src/main/java/org/fuin/objects4j/common/package-info.java b/common/src/main/java/org/fuin/objects4j/common/package-info.java index a0db608..2f189c0 100644 --- a/common/src/main/java/org/fuin/objects4j/common/package-info.java +++ b/common/src/main/java/org/fuin/objects4j/common/package-info.java @@ -19,6 +19,6 @@ */ /** - * Contains base classes like utilities and general annotation. + * Some interfaces, annotations and validators. */ package org.fuin.objects4j.common; diff --git a/common/src/test/java/org/fuin/objects4j/common/HasPublicStaticIsValidMethodValidatorTest.java b/common/src/test/java/org/fuin/objects4j/common/HasPublicStaticIsValidMethodValidatorTest.java index 260e3e7..fcc5b97 100644 --- a/common/src/test/java/org/fuin/objects4j/common/HasPublicStaticIsValidMethodValidatorTest.java +++ b/common/src/test/java/org/fuin/objects4j/common/HasPublicStaticIsValidMethodValidatorTest.java @@ -137,7 +137,7 @@ private static String first(Set violations) { return violations.stream().map(v -> ((ConstraintViolation) v).getMessage()).findFirst().orElse(null); } - @HasPublicStaticIsValidMethod + @HasPublicStaticIsValidMethod(method = "isValid", param = String.class) public static final class MyClassValid { public static boolean isValid(String str) { if (str == null) { diff --git a/core/README.md b/core/README.md new file mode 100644 index 0000000..b3622d7 --- /dev/null +++ b/core/README.md @@ -0,0 +1,37 @@ +# objects4j-core +A library with common Java types that are mostly immutable value objects. + +## Description +Provides Value Objects (immutable objects) that represents an object whose equality isn't based on identity. +That means instances of this type are equal when they have the same value, not necessarily being the same object. +Additionally, some helper classes (like validators) are placed in this package. + +**Base classes** that allow an easy implementation of concrete classes. +* [AbstractIntegerValueObject](src/main/java/org/fuin/objects4j/core/AbstractIntegerValueObject.java) - A value object that is based on an integer. +* [AbstractLongValueObject](src/main/java/org/fuin/objects4j/core/AbstractLongValueObject.java) - A value object that is based on a long. +* [AbstractStringValueObject](src/main/java/org/fuin/objects4j/core/AbstractStringValueObject.java) - A value object that is based on a string. +* [AbstractUuidValueObject](src/main/java/org/fuin/objects4j/core/AbstractUuidValueObject.java) - A value object that is based on a UUID. + +**Predefined Value Objects** +* [CurrencyAmount](src/main/java/org/fuin/objects4j/core/CurrencyAmount.java) - Combines a currency (like "USD" or "EUR") with a big decimal value (like "**512 EUR**"). There is also a [CurrencyAmountConverter](src/main/java/org/fuin/objects4j/core/CurrencyAmountConverter.java) (JAX-B, JSON-B and JPA) and a [CurrencyAmountValidator](src/main/java/org/fuin/objects4j/core/CurrencyAmountValidator.java) (```@CurrencyAmountStr```) available. +* [EmailAddress](src/main/java/org/fuin/objects4j/core/EmailAddress.java) - Email address. There is also a [EmailAddressConverter](src/main/java/org/fuin/objects4j/core/EmailAddressConverter.java) (JAX-B, JSON-B and JPA) and a [EmailAddressValidator](src/main/java/org/fuin/objects4j/core/EmailAddressValidator.java) (```@EmailAddressStr```) available. +* [Password](src/main/java/org/fuin/objects4j/core/Password.java) - A password with a length between 8 and 20 characters. There is also a [PasswordConverter](src/main/java/org/fuin/objects4j/core/PasswordConverter.java) (JAX-B, JSON-B and JPA) and a [PasswordValidator](src/main/java/org/fuin/objects4j/core/PasswordValidator.java) (```@PasswordStr```) available. +* [PasswordSha512](src/main/java/org/fuin/objects4j/core/PasswordSha512.java) - A SHA-512 hashed password that is HEX encoded. There is also a [PasswordSha512Converter](src/main/java/org/fuin/objects4j/core/PasswordSha512Converter.java) (JAX-B, JSON-B and JPA) and a [PasswordSha512Validator](src/main/java/org/fuin/objects4j/core/PasswordSha512Validator.java) (```@PasswordSha512Str```) available. +* [UserName](src/main/java/org/fuin/objects4j/core/UserName.java) - User name with restricted character set and length. There is also a [UserNameConverter](src/main/java/org/fuin/objects4j/core/UserNameConverter.java) (JAX-B, JSON-B and JPA) and a [UserNameValidator](src/main/java/org/fuin/objects4j/core/UserNameValidator.java) (```@UserNameStr```) available. +* [Hour](src/main/java/org/fuin/objects4j/core/Hour.java) - Hour of a day like '**23:59**' (24 hours, sometimes called Military Time). There is also an [HourConverter](src/main/java/org/fuin/objects4j/core/HourConverter.java) (JAX-B, JSON-B and JPA) and an [HourStrValidator](src/main/java/org/fuin/objects4j/core/HourStrValidator.java) (```@HourStr```) available. +* [HourRange](src/main/java/org/fuin/objects4j/core/HourRange.java) - Range of hours of a day like '**00:00-24:00**' (24 hours, sometimes called Military Time). There is also an [HourRangeConverter](src/main/java/org/fuin/objects4j/core/HourRangeConverter.java) (JAX-B, JSON-B and JPA) and an [HourRangeStrValidator](src/main/java/org/fuin/objects4j/core/HourRangeStrValidator.java) (```@HourRangeStr```) available. +* [HourRanges](src/main/java/org/fuin/objects4j/core/HourRanges.java) - Multiple range of hours of a day like '**09:00-12:00+13:00-17:00**'. There is also an [HourRangesConverter](src/main/java/org/fuin/objects4j/core/HourRangesConverter.java) (JAX-B, JSON-B and JPA) and an [HourRangesStrValidator](src/main/java/org/fuin/objects4j/core/HourRangesStrValidator.java) (```@HourRangesStr```) available. +* [DayOfTheWeek](src/main/java/org/fuin/objects4j/core/DayOfTheWeek.java) - The days of the week '**Mon**'-'**Sun**'(from Monday to Sunday) plus '**PH**' (Public Holiday). There is also an [DayOfTheWeekConverter](src/main/java/org/fuin/objects4j/core/DayOfTheWeekConverter.java) (JAX-B, JSON-B and JPA) and an [DayOfTheWeekStrValidator](src/main/java/org/fuin/objects4j/core/DayOfTheWeekStrValidator.java) (```@DayOfTheWeekStr```) available. +* [MultiDayOfTheWeek](src/main/java/org/fuin/objects4j/core/MultiDayOfTheWeek.java) - Multiple days of the week like '**Mon/Tue/Wed-Fri/PH**' (Monday AND Tuesday AND Wednesday TO Friday AND Public Holidays). There is also an [MultiDayOfTheWeekConverter](src/main/java/org/fuin/objects4j/core/MultiDayOfTheWeekConverter.java) (JAX-B, JSON-B and JPA) and an [MultiDayOfTheWeekStrValidator](src/main/java/org/fuin/objects4j/core/MultiDayOfTheWeekStrValidator.java) (```@MultiDayOfTheWeekStr```) available. +* [DayOpeningHours](src/main/java/org/fuin/objects4j/core/DayOpeningHours.java) - Multiple range of hours of single a day like '**Mon 09:00-12:00+13:00-17:00**'. There is also an [DayOpeningHoursConverter](src/main/java/org/fuin/objects4j/core/DayOpeningHoursConverter.java) (JAX-B, JSON-B and JPA) and an [DayOpeningHoursStrValidator](src/main/java/org/fuin/objects4j/core/DayOpeningHoursStrValidator.java) (```@DayOpeningHoursStr```) available. +* [WeeklyOpeningHours](src/main/java/org/fuin/objects4j/core/WeeklyOpeningHours.java) - weekly opening hours separated by a comma like '**Mon-Fri 09:00-12:00+13:00-17:00,Sat/Sun 09:-12:00**'. There is also an [WeeklyOpeningHoursConverter](src/main/java/org/fuin/objects4j/core/WeeklyOpeningHoursConverter.java) (JAX-B, JSON-B and JPA) and an [WeeklyOpeningHoursStrValidator](src/main/java/org/fuin/objects4j/core/WeeklyOpeningHoursStrValidator.java) (```@WeeklyOpeningHoursStr```) available. + +**Validators** +* [DateStrValidator](src/main/java/org/fuin/objects4j/core/DateStrValidator.java) - Validates that a string is a date using the current locale ([@DateStr](src/main/java/org/fuin/objects4j/core/DateStr.java)). +* [LocaleStrValidator](src/main/java/org/fuin/objects4j/core/LocaleStrValidator.java) - Validates that a string is a valid locale ([@LocaleStr](src/main/java/org/fuin/objects4j/core/LocaleStr.java)). +* [PropertiesContainValidator](src/main/java/org/fuin/objects4j/core/PropertiesContainValidator.java) - Validates that a string is one out of a list of constants ([@PropertiesContain("one", "two", "three")](src/main/java/org/fuin/objects4j/core/PropertiesContain.java)). +* [TrimmedNotEmptyValidator](src/main/java/org/fuin/objects4j/core/TrimmedNotEmptyValidator.java) - Validates that a string is not empty after it was trimmed [@TrimmedNotEmpty](src/main/java/org/fuin/objects4j/core/TrimmedNotEmpty.java) +* [UUIDStrValidator](src/main/java/org/fuin/objects4j/core/UUIDStrValidator.java) - Validates that a string is a valid UUID ([@UUIDStr](src/main/java/org/fuin/objects4j/core/UUIDStr.java)). + +**Other** +* [KeyValue](src/main/java/org/fuin/objects4j/core/KeyValue.java) - Container for a key (String) and a value (Object). diff --git a/core/src/main/java/org/fuin/objects4j/core/AbstractIntegerValueObject.java b/core/src/main/java/org/fuin/objects4j/core/AbstractIntegerValueObject.java index d3dd015..da9904e 100644 --- a/core/src/main/java/org/fuin/objects4j/core/AbstractIntegerValueObject.java +++ b/core/src/main/java/org/fuin/objects4j/core/AbstractIntegerValueObject.java @@ -17,6 +17,8 @@ */ package org.fuin.objects4j.core; +import org.fuin.objects4j.common.ValueObjectWithBaseType; + import java.io.Serial; import java.io.Serializable; diff --git a/core/src/main/java/org/fuin/objects4j/core/AbstractLongValueObject.java b/core/src/main/java/org/fuin/objects4j/core/AbstractLongValueObject.java index ec09357..5dec2be 100644 --- a/core/src/main/java/org/fuin/objects4j/core/AbstractLongValueObject.java +++ b/core/src/main/java/org/fuin/objects4j/core/AbstractLongValueObject.java @@ -17,6 +17,8 @@ */ package org.fuin.objects4j.core; +import org.fuin.objects4j.common.ValueObjectWithBaseType; + import java.io.Serial; import java.io.Serializable; diff --git a/core/src/main/java/org/fuin/objects4j/core/AbstractStringValueObject.java b/core/src/main/java/org/fuin/objects4j/core/AbstractStringValueObject.java index 21b5cd3..41c5fe8 100644 --- a/core/src/main/java/org/fuin/objects4j/core/AbstractStringValueObject.java +++ b/core/src/main/java/org/fuin/objects4j/core/AbstractStringValueObject.java @@ -17,6 +17,9 @@ */ package org.fuin.objects4j.core; +import org.fuin.objects4j.common.AsStringCapable; +import org.fuin.objects4j.common.ValueObjectWithBaseType; + import java.io.Serial; import java.io.Serializable; diff --git a/core/src/main/java/org/fuin/objects4j/core/AbstractUuidValueObject.java b/core/src/main/java/org/fuin/objects4j/core/AbstractUuidValueObject.java index 0071530..da34d70 100644 --- a/core/src/main/java/org/fuin/objects4j/core/AbstractUuidValueObject.java +++ b/core/src/main/java/org/fuin/objects4j/core/AbstractUuidValueObject.java @@ -18,6 +18,7 @@ package org.fuin.objects4j.core; import org.fuin.objects4j.common.HasPublicStaticIsValidMethod; +import org.fuin.objects4j.common.ValueObjectWithBaseType; import java.io.Serial; import java.io.Serializable; diff --git a/core/src/main/java/org/fuin/objects4j/core/CurrencyAmount.java b/core/src/main/java/org/fuin/objects4j/core/CurrencyAmount.java index 2452917..11ce804 100644 --- a/core/src/main/java/org/fuin/objects4j/core/CurrencyAmount.java +++ b/core/src/main/java/org/fuin/objects4j/core/CurrencyAmount.java @@ -19,10 +19,12 @@ import jakarta.annotation.Nullable; import jakarta.validation.constraints.NotNull; +import org.fuin.objects4j.common.AsStringCapable; import org.fuin.objects4j.common.ConstraintViolationException; import org.fuin.objects4j.common.Contract; import org.fuin.objects4j.common.HasPublicStaticIsValidMethod; import org.fuin.objects4j.common.HasPublicStaticValueOfMethod; +import org.fuin.objects4j.common.ValueObjectWithBaseType; import org.fuin.objects4j.ui.Label; import org.fuin.objects4j.ui.ShortLabel; diff --git a/core/src/main/java/org/fuin/objects4j/core/DayOfTheWeek.java b/core/src/main/java/org/fuin/objects4j/core/DayOfTheWeek.java index e6d9b17..2245034 100644 --- a/core/src/main/java/org/fuin/objects4j/core/DayOfTheWeek.java +++ b/core/src/main/java/org/fuin/objects4j/core/DayOfTheWeek.java @@ -20,10 +20,12 @@ import jakarta.annotation.Nullable; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import org.fuin.objects4j.common.AsStringCapable; import org.fuin.objects4j.common.ConstraintViolationException; import org.fuin.objects4j.common.Contract; import org.fuin.objects4j.common.HasPublicStaticIsValidMethod; import org.fuin.objects4j.common.HasPublicStaticValueOfMethod; +import org.fuin.objects4j.common.ValueObjectWithBaseType; import org.fuin.objects4j.ui.Label; import org.fuin.objects4j.ui.Prompt; import org.fuin.objects4j.ui.ShortLabel; diff --git a/core/src/main/java/org/fuin/objects4j/core/DayOpeningHours.java b/core/src/main/java/org/fuin/objects4j/core/DayOpeningHours.java index 2a32d95..ac4db8d 100644 --- a/core/src/main/java/org/fuin/objects4j/core/DayOpeningHours.java +++ b/core/src/main/java/org/fuin/objects4j/core/DayOpeningHours.java @@ -20,10 +20,12 @@ import jakarta.annotation.Nullable; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import org.fuin.objects4j.common.AsStringCapable; import org.fuin.objects4j.common.ConstraintViolationException; import org.fuin.objects4j.common.Contract; import org.fuin.objects4j.common.HasPublicStaticIsValidMethod; import org.fuin.objects4j.common.HasPublicStaticValueOfMethod; +import org.fuin.objects4j.common.ValueObjectWithBaseType; import org.fuin.objects4j.core.HourRanges.ChangeType; import org.fuin.objects4j.ui.Prompt; diff --git a/core/src/main/java/org/fuin/objects4j/core/KeyValue.java b/core/src/main/java/org/fuin/objects4j/core/KeyValue.java index 059b42c..501648b 100644 --- a/core/src/main/java/org/fuin/objects4j/core/KeyValue.java +++ b/core/src/main/java/org/fuin/objects4j/core/KeyValue.java @@ -19,6 +19,7 @@ import jakarta.validation.constraints.NotNull; import org.fuin.objects4j.common.Contract; +import org.fuin.objects4j.common.ValueObject; import javax.annotation.concurrent.Immutable; import java.util.Collection; diff --git a/jackson/README.md b/jackson/README.md new file mode 100644 index 0000000..c39f623 --- /dev/null +++ b/jackson/README.md @@ -0,0 +1,21 @@ +# objects4j-jackson +FasterXML [Jackson](https://github.com/FasterXML/jackson) JSON serializer/deserializer for the types defined in [Core](../core). + +## Getting started +Simply add the [Objects4JJacksonAdapterModule](src/main/java/org/fuin/objects4j/jackson/Objects4JJacksonAdapterModule.java) +to your object mapper to activate the serializers and deserializer. + +```java +@Configuration +public class SpringBootConfig { + + @Bean + @Primary + public ObjectMapper jsonMapper() { + return new ObjectMapper() + .setSerializationInclusion(JsonInclude.Include.NON_NULL) + .registerModule(new Objects4JJacksonAdapterModule()); + } + +} +``` diff --git a/jackson/src/main/java/org/fuin/objects4j/jackson/ValueObjectStringJacksonDeserializer.java b/jackson/src/main/java/org/fuin/objects4j/jackson/ValueObjectStringJacksonDeserializer.java index 920d900..ecde819 100644 --- a/jackson/src/main/java/org/fuin/objects4j/jackson/ValueObjectStringJacksonDeserializer.java +++ b/jackson/src/main/java/org/fuin/objects4j/jackson/ValueObjectStringJacksonDeserializer.java @@ -23,8 +23,8 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import jakarta.validation.constraints.NotNull; import org.fuin.objects4j.common.Contract; -import org.fuin.objects4j.core.AsStringCapable; -import org.fuin.objects4j.core.ValueOfCapable; +import org.fuin.objects4j.common.AsStringCapable; +import org.fuin.objects4j.common.ValueOfCapable; import java.io.IOException; diff --git a/jackson/src/main/java/org/fuin/objects4j/jackson/ValueObjectStringJacksonSerializer.java b/jackson/src/main/java/org/fuin/objects4j/jackson/ValueObjectStringJacksonSerializer.java index eef752d..d6251c2 100644 --- a/jackson/src/main/java/org/fuin/objects4j/jackson/ValueObjectStringJacksonSerializer.java +++ b/jackson/src/main/java/org/fuin/objects4j/jackson/ValueObjectStringJacksonSerializer.java @@ -21,8 +21,8 @@ import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import jakarta.validation.constraints.NotNull; -import org.fuin.objects4j.core.AsStringCapable; -import org.fuin.objects4j.core.ValueOfCapable; +import org.fuin.objects4j.common.AsStringCapable; +import org.fuin.objects4j.common.ValueOfCapable; import java.io.IOException; diff --git a/jaxb/README.md b/jaxb/README.md new file mode 100644 index 0000000..7388232 --- /dev/null +++ b/jaxb/README.md @@ -0,0 +1,25 @@ +# objects4j-jaxb +Jakarta XML Binding ([JAX-B](https://jakarta.ee/specifications/xml-binding/3.0/jakarta-xml-binding-spec-3.0)) XML adapters for the types defined in [Core](../core). + +## Getting started +Simply add an [@XmlJavaTypeAdapter](https://jakarta.ee/specifications/platform/9/apidocs/jakarta/xml/bind/annotation/adapters/xmljavatypeadapter) to your field: +```java +@XmlRootElement +public class Data { + + @XmlAttribute + @XmlJavaTypeAdapter(EmailAddressXmlAdapter.class) + private EmailAddress email; + +} +``` +You can also create a `package-info.java` file and add all the adapters at once: +```java +@XmlJavaTypeAdapter(EmailAddressXmlAdapter.class) +@XmlJavaTypeAdapter(CurrencyXmlAdapter.class) +package foo.bar; + +import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import org.fuin.objects4j.jaxb.CurrencyXmlAdapter; +import org.fuin.objects4j.jaxb.EmailAddressXmlAdapter; +``` diff --git a/jaxb/src/main/java/org/fuin/objects4j/jaxb/ValueObjectStringXmlAdapter.java b/jaxb/src/main/java/org/fuin/objects4j/jaxb/ValueObjectStringXmlAdapter.java index f46c82d..ff7e64a 100644 --- a/jaxb/src/main/java/org/fuin/objects4j/jaxb/ValueObjectStringXmlAdapter.java +++ b/jaxb/src/main/java/org/fuin/objects4j/jaxb/ValueObjectStringXmlAdapter.java @@ -20,8 +20,8 @@ import jakarta.validation.constraints.NotNull; import jakarta.xml.bind.annotation.adapters.XmlAdapter; import org.fuin.objects4j.common.Contract; -import org.fuin.objects4j.core.AsStringCapable; -import org.fuin.objects4j.core.ValueOfCapable; +import org.fuin.objects4j.common.AsStringCapable; +import org.fuin.objects4j.common.ValueOfCapable; /** * Converts a type into a string and back. diff --git a/jpa/README.md b/jpa/README.md new file mode 100644 index 0000000..6390012 --- /dev/null +++ b/jpa/README.md @@ -0,0 +1,23 @@ +# objects4j-jpa +Jakarta Persistence API ([JPA](https://jakarta.ee/specifications/persistence/3.1/jakarta-persistence-spec-3.1)) attribute converters for the types defined in [Core](../core). + +## Getting started +Simply add [@Convert](https://jakarta.ee/specifications/persistence/3.1/apidocs/jakarta.persistence/jakarta/persistence/convert) to your field: +```java +@Entity(name = "EMAIL_ADDRESS_PARENT") +public class EmailAddressParentEntity { + + @Column(name = "EMAIL", nullable = true) + @Convert(converter = EmailAddressAttributeConverter.class) + private EmailAddress emailAddress; +``` +You can also create a `package-info.java` file and add all the converters at once if you use Hibernate's [@ConverterRegistration](https://docs.jboss.org/hibernate/orm/6.3/javadocs/org/hibernate/annotations/ConverterRegistration.html) annotation: +```java +@ConverterRegistration(converter = FooConverter.class, autoApply = true) +@ConverterRegistration(converter = CurrencyAttributeConverter.class, autoApply = true) +package foo.bar; + +import org.hibernate.annotations.ConverterRegistration; +import org.fuin.objects4j.jaxb.CurrencyXmlAdapter; +import org.fuin.objects4j.jjpa.EmailAddressAttributeConverter; +``` diff --git a/jpa/src/main/java/org/fuin/objects4j/jpa/ValueObjectStringAttributeConverter.java b/jpa/src/main/java/org/fuin/objects4j/jpa/ValueObjectStringAttributeConverter.java index 7593950..80486f0 100644 --- a/jpa/src/main/java/org/fuin/objects4j/jpa/ValueObjectStringAttributeConverter.java +++ b/jpa/src/main/java/org/fuin/objects4j/jpa/ValueObjectStringAttributeConverter.java @@ -20,8 +20,8 @@ import jakarta.persistence.AttributeConverter; import jakarta.validation.constraints.NotNull; import org.fuin.objects4j.common.Contract; -import org.fuin.objects4j.core.AsStringCapable; -import org.fuin.objects4j.core.ValueOfCapable; +import org.fuin.objects4j.common.AsStringCapable; +import org.fuin.objects4j.common.ValueOfCapable; /** * Converts a type into a string and back. diff --git a/jpa/src/test/java/org/fuin/objects4j/jpa/CurrencyParentEntity.java b/jpa/src/test/java/org/fuin/objects4j/jpa/CurrencyParentEntity.java index 4a991cf..4058999 100644 --- a/jpa/src/test/java/org/fuin/objects4j/jpa/CurrencyParentEntity.java +++ b/jpa/src/test/java/org/fuin/objects4j/jpa/CurrencyParentEntity.java @@ -34,7 +34,6 @@ public class CurrencyParentEntity { @Convert(converter = CurrencyAttributeConverter.class) @Column(name = "CURRENCY", nullable = true) - @Basic private Currency currency; public CurrencyParentEntity() { diff --git a/jsonb/README.md b/jsonb/README.md new file mode 100644 index 0000000..76ea4f9 --- /dev/null +++ b/jsonb/README.md @@ -0,0 +1,22 @@ +# objects4j-jsonb +Jakarta JSON Binding ([JSON-B](https://jakarta.ee/specifications/jsonb/3.0/jakarta-jsonb-spec-3.0)) adapters for the types defined in [Core](../core). + +## Getting started +Simply add an [@JsonbTypeAdapter](https://jakarta.ee/specifications/platform/9/apidocs/jakarta/json/bind/annotation/jsonbtypeadapter) to your field: +```java +public class Data { + + @JsonbProperty + @JsonbTypeAdapter(EmailAddressJsonbAdapter.class) + public EmailAddress email; + +} +``` +You can also use the [JsonbUtils.getJsonbAdapters()](src/main/java/org/fuin/objects4j/jsonb/JsonbUtils.java) method to add all adapters to the [JsonbConfig](https://jakarta.ee/specifications/platform/9/apidocs/jakarta/json/bind/jsonbconfig): +```java +public static String toJson(final T obj) { + final JsonbConfig config = new JsonbConfig().withAdapters(JsonbUtils.getJsonbAdapterArray()); + final Jsonb jsonb = JsonbBuilder.create(config); + return jsonb.toJson(obj, obj.getClass()); +} +``` diff --git a/jsonb/src/main/java/org/fuin/objects4j/jsonb/JsonbUtils.java b/jsonb/src/main/java/org/fuin/objects4j/jsonb/JsonbUtils.java index 71ce7ec..c36ba74 100644 --- a/jsonb/src/main/java/org/fuin/objects4j/jsonb/JsonbUtils.java +++ b/jsonb/src/main/java/org/fuin/objects4j/jsonb/JsonbUtils.java @@ -39,4 +39,13 @@ private JsonbUtils() { return new ArrayList<>(ADAPTERS); } + /** + * Returns an array of {@link JsonbAdapter} objects defined by the package. + * + * @return Array with adapters. + */ + public static JsonbAdapter[] getJsonbAdapterArray() { + return getJsonbAdapters().toArray(new JsonbAdapter[0]); + } + } diff --git a/jsonb/src/main/java/org/fuin/objects4j/jsonb/ValueObjectStringJsonbAdapter.java b/jsonb/src/main/java/org/fuin/objects4j/jsonb/ValueObjectStringJsonbAdapter.java index 3171235..d423c28 100644 --- a/jsonb/src/main/java/org/fuin/objects4j/jsonb/ValueObjectStringJsonbAdapter.java +++ b/jsonb/src/main/java/org/fuin/objects4j/jsonb/ValueObjectStringJsonbAdapter.java @@ -20,8 +20,8 @@ import jakarta.json.bind.adapter.JsonbAdapter; import jakarta.validation.constraints.NotNull; import org.fuin.objects4j.common.Contract; -import org.fuin.objects4j.core.AsStringCapable; -import org.fuin.objects4j.core.ValueOfCapable; +import org.fuin.objects4j.common.AsStringCapable; +import org.fuin.objects4j.common.ValueOfCapable; /** * Converts a type into a string and back. diff --git a/junit/README.md b/junit/README.md new file mode 100644 index 0000000..bc5f6fb --- /dev/null +++ b/junit/README.md @@ -0,0 +1,28 @@ +# objects4j-junit +Defines [ArchUnit](https://www.archunit.org/) conditions for classes depending on this library. + +See [ArchitectureBaseTest.java](src/test/java/org/fuin/objects4j/junit/ArchitectureBaseTest.java) for a full usage example. + +## Verify that classes using [@HasPublicStaticIsValidMethod](../common/src/main/java/org/fuin/objects4j/common/HasPublicStaticIsValidMethod.java) really have such a method. +```java +@ArchTest +static final ArchRule verify_public_static_is_valid_annotations = + classes() + .that() + .doNotHaveModifier(JavaModifier.ABSTRACT) + .and() + .areAnnotatedWith(HasPublicStaticIsValidMethod.class) + .should(haveACorrespondingPublicStaticIsValidMethod()); +``` + +## Verify that classes using [@HasPublicStaticValueOfMethod](../common/src/main/java/org/fuin/objects4j/common/HasPublicStaticValueOfMethod.java) really have such a method. +```java +@ArchTest +static final ArchRule verify_public_static_value_of_annotations = + classes() + .that() + .doNotHaveModifier(JavaModifier.ABSTRACT) + .and() + .areAnnotatedWith(HasPublicStaticValueOfMethod.class) + .should(haveACorrespondingPublicStaticValueOfMethod()); +``` \ No newline at end of file diff --git a/junit/src/test/java/org/fuin/objects4j/junit/ArchitectureBaseTest.java b/junit/src/test/java/org/fuin/objects4j/junit/ArchitectureBaseTest.java index 0f4c20b..42b3c14 100644 --- a/junit/src/test/java/org/fuin/objects4j/junit/ArchitectureBaseTest.java +++ b/junit/src/test/java/org/fuin/objects4j/junit/ArchitectureBaseTest.java @@ -9,9 +9,9 @@ import org.fuin.objects4j.common.HasPublicStaticIsValidMethods; import org.fuin.objects4j.common.HasPublicStaticValueOfMethod; import org.fuin.objects4j.common.HasPublicStaticValueOfMethods; -import org.fuin.objects4j.core.AsStringCapable; +import org.fuin.objects4j.common.ValueObjectWithBaseType; +import org.fuin.objects4j.core.AbstractStringValueObject; import org.fuin.objects4j.core.Password; -import org.fuin.objects4j.core.ValueObjectWithBaseType; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; import static org.fuin.objects4j.junit.Objects4Conditions.haveACorrespondingPublicStaticIsValidMethod; @@ -22,7 +22,7 @@ *

* The tests are located in this module and not in the affected modules to avoid a circular dependency. */ -@AnalyzeClasses(packagesOf = AsStringCapable.class, importOptions = ImportOption.DoNotIncludeTests.class) +@AnalyzeClasses(packagesOf = AbstractStringValueObject.class, importOptions = ImportOption.DoNotIncludeTests.class) public class ArchitectureBaseTest { @ArchTest diff --git a/new-module-structure.md b/new-module-structure.md index 30ab402..088ea15 100644 --- a/new-module-structure.md +++ b/new-module-structure.md @@ -1,2 +1,36 @@ # New Module Structure +Starting with version `0.10.0` the classes where moved to separate modules. +This allows to avoid unnecessary dependencies on external libraries that are not wanted. +For example the `EmailAddress` class used a `@XmlJavaTypeAdapter` annotation which leads to a dependency +on JAX-B, even if you use another mapping framework like Jackson. +## New Maven Group ID +- OLD: `org.fuin` +- NEW: `org.fuin.objects4j` + +## New Maven modules +The classes where moved to different modules/packages. +- [common](common) - Package `org.fuin.objects4j.common` +- [core](core) - Package `org.fuin.objects4j.core` +- [jackson](jackson) - Package `org.fuin.objects4j.jackson` (NEW functionality) +- [jaxb](jaxb) - Package `org.fuin.objects4j.jaxb` +- [jpa](jpa) - Package `org.fuin.objects4j.jpa` +- [jsonb](jsonb) - Package `org.fuin.objects4j.jsonb` +- [junit](junit) - Package `org.fuin.objects4j.junit` (NEW functionality) +- [ui](ui) - Package `org.fuin.objects4j.ui` + +## Converter split +Previously the `Converter` classes depended on three external libraries and these packages: +- JAX-B: `jakarta.xml.bind.annotation.adapters.XmlAdapter` +- JSON-B: `jakarta.json.bind.adapter.JsonbAdapter` +- JPA: `jakarta.persistence.AttributeConverter` + +Now there are separate converters for these external libraries: +- [jaxb](jaxb) - `*XmlAdapter` in package `org.fuin.objects4j.jaxb` +- [jpa](jpa) - `*AttributeConverter` in package `org.fuin.objects4j.jpa` +- [jsonb](jsonb) - `*JsonbAdapter` in package `org.fuin.objects4j.jsonb` + +## No more JPA 'autoApply' +Previously the converter classes where annotated with `@Converter(autoApply = true)`. +This was removed, and you will need to add the converter either directly to your field +or create a `package-info.java` file and add all the converters at once (only possible with Hibernate). diff --git a/ui/README.md b/ui/README.md new file mode 100644 index 0000000..0a736ec --- /dev/null +++ b/ui/README.md @@ -0,0 +1,126 @@ +# objects4j-ui +Annotations that can be placed on plain objects but may be used by a user interface to render that object in some way. + +* [Label annotation](#label-annotation) +* [Prompt annotation](#prompt-annotation) +* [ShortLabel annotation](#shortlabel-annotation) +* [TableColumn annotation](#tablecolumn-annotation) +* [TextField annotation](#textfield-annotation) +* [Tooltip annotation](#tooltip-annotation) + +## Description +The annotations may be used by UI elements to display an appropriate text for a type or a field. +You can also configure a bundle and key for internationalization. + +### Label annotation +Use this annotation to assign a label to a class or an attribute. +```Java +@Label(value = "Birthday", bundle = "my/MyBundle", key = "birthday.label") +private Date birthday; +``` + +### Prompt annotation +Use this annotation to assign a prompt (example value) to a class or an attribute. +```Java +@Prompt(value = "12-31-1993", bundle = "my/MyBundle", key = "birthday.prompt") +private Date birthday; +``` + +### ShortLabel annotation +Use this annotation to assign an abbreviation to a class or an attribute. +```Java +@ShortLabel(value = "BD", bundle = "my/MyBundle", key = "birthday.short") +private Date birthday; +``` + +### TableColumn annotation +Use this annotation to assign preferred table column values to a field. +```Java +@TableColumn(pos = 3, width = 20, unit= FontSizeUnit.EM, getter = "isInternal") +private boolean permanentEmployee; +``` + +### TextField annotation +Use this annotation to express the annotated attribute should be rendered as a text field. +User agents are expected to use this information as hint for the rendering process. +```Java +@TextField(width = 50) +private String lastName; +``` + +### Tooltip annotation +Use this annotation to assign a tooltip to a class or a field. +```Java +@Tooltip(value = "The person's birthday", bundle = "my/MyBundle", key = "birthday.tooltip") +private Date birthday; +``` + +### AnnotationAnalyzer +You can use [AnnotationAnalyzer](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/AnnotationAnalyzer.java) to read the internationalized text from above annotations. + +Read a single ```@Label``` text: +```Java +AnnotationAnalyzer analyzer = new AnnotationAnalyzer(); + +Field field = MyClass.class.getDeclaredField("birthday"); + +FieldTextInfo labelInfoGermany = analyzer.createFieldInfo(field, Locale.GERMANY, Label.class); +System.out.println(labelInfoGermany.getText()); +// Prints "Geburtstag" + +FieldTextInfo labelInfoUs = analyzer.createFieldInfo(field, Locale.US, Label.class); +System.out.println(labelInfoUs.getText()); +// Prints "Birthday" +``` + +Read all ```@Label``` texts from a class: +```Java +AnnotationAnalyzer analyzer = new AnnotationAnalyzer(); +List infos = analyzer.createFieldInfos(MyClass.class, Locale.US, Label.class); +for (final FieldTextInfo info : infos) { + // Text of the label or the name of the field if the text is null + System.out.println(info.getTextOrField()); +} +``` + +Create a list of [TableColumnInfo](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/TableColumnInfo.java) +that combines [@Label](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/Label.java), +[@ShortLabel](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/ShortLabel.java) and +[@TableColumn](https://github.com/fuinorg/objects4j/blob/master/src/main/java/org/fuin/objects4j/ui/TableColumn.java) annotations. +```Java +List columns = TableColumnInfo.create(MyClass.class, Locale.US); +for (TableColumnInfo column : columns) { + System.out.println(column.getText()); +} +``` + +This allows easy creation of a table model for example for JavaFX: +```Java +TableView tableView = new TableView<>(); +List tableCols = TableColumnInfo.create(MyClass.class, Locale.getDefault()); +Collections.sort(tableCols); +for (TableColumnInfo column : tableCols) { + TableColumn tc = new TableColumn<>(); + tc.setStyle("-fx-alignment: CENTER;"); + Label label = new Label(column.getShortText()); + label.setTooltip(new Tooltip(column.getTooltip())); + tc.setGraphic(label); + tc.setCellValueFactory(new PropertyValueFactory(column.getField().getName())); + tc.setPrefWidth(column.getWidth().getSize()); + tableView.getColumns().add(tc); +} +``` + +### Examples annotation +Use this annotation to assign some example values to a class or an attribute. +```Java +@Examples({"John", "Jane"}) +private String firstName; +``` + +### Mappings annotation +Use this annotation to assign key/value mappings to a class or an attribute. +```Java +@Mappings({"1=One", "2=Two", "3=Three"}) +private String code; +```