Copyright.java
001 /*
002  * Java GPX Library (jpx-3.1.0).
003  * Copyright (c) 2016-2023 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019  */
020 package io.jenetics.jpx;
021 
022 import static java.util.Objects.hash;
023 import static java.util.Objects.requireNonNull;
024 import static io.jenetics.jpx.Format.parseURI;
025 import static io.jenetics.jpx.Format.toUriString;
026 import static io.jenetics.jpx.Format.toYearString;
027 
028 import java.io.DataInput;
029 import java.io.DataOutput;
030 import java.io.IOException;
031 import java.io.InvalidObjectException;
032 import java.io.ObjectInputStream;
033 import java.io.Serial;
034 import java.io.Serializable;
035 import java.net.URI;
036 import java.time.Year;
037 import java.util.Objects;
038 import java.util.Optional;
039 
040 /**
041  * Information about the copyright holder and any license governing use of this
042  * file. By linking to an appropriate license, you may place your data into the
043  * public domain or grant additional usage rights.
044  *
045  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
046  @version 1.2
047  @since 1.0
048  */
049 public final class Copyright implements Serializable {
050 
051     @Serial
052     private static final long serialVersionUID = 2L;
053 
054     private final String _author;
055     private final Year _year;
056     private final URI _license;
057 
058     /**
059      * Create a new {@code Copyright} object with the given data.
060      *
061      @param author copyright holder (TopoSoft, Inc.)
062      @param year year of copyright.
063      @param license link to external file containing license text.
064      @throws NullPointerException if the {@code author} is {@code null}
065      */
066     private Copyright(final String author, final Year year, final URI license) {
067         _author = requireNonNull(author);
068         _year = year;
069         _license = license;
070     }
071 
072     /**
073      * Return the copyright holder.
074      *
075      @return the copyright holder
076      */
077     public String getAuthor() {
078         return _author;
079     }
080 
081     /**
082      * Return the year of copyright.
083      *
084      @return the year of copyright
085      */
086     public Optional<Year> getYear() {
087         return Optional.ofNullable(_year);
088     }
089 
090     /**
091      * Return the link to external file containing license text.
092      *
093      @return link to external file containing license text
094      */
095     public Optional<URI> getLicense() {
096         return Optional.ofNullable(_license);
097     }
098 
099     @Override
100     public int hashCode() {
101         return hash(_author, _year, _license);
102     }
103 
104     @Override
105     public boolean equals(final Object obj) {
106         return obj == this ||
107             obj instanceof Copyright cr &&
108             Objects.equals(cr._author, _author&&
109             Objects.equals(cr._year, _year&&
110             Objects.equals(cr._license, _license);
111     }
112 
113     @Override
114     public String toString() {
115         return _author + getYear().map(y -> " (c) " + y).orElse("");
116     }
117 
118 
119     /* *************************************************************************
120      *  Static object creation methods
121      * ************************************************************************/
122 
123     /**
124      * Create a new {@code Copyright} object with the given data.
125      *
126      @param author copyright holder (TopoSoft, Inc.)
127      @param year year of copyright.
128      @param license link to external file containing license text.
129      @return a new {@code Copyright} object with the given data
130      @throws NullPointerException if the {@code author} is {@code null}
131      */
132     public static Copyright of(
133         final String author,
134         final Year year,
135         final URI license
136     ) {
137         return new Copyright(author, year, license);
138     }
139 
140     /**
141      * Create a new {@code Copyright} object with the given data.
142      *
143      @param author copyright holder (TopoSoft, Inc.)
144      @param year year of copyright.
145      @param license link to external file containing license text.
146      @return a new {@code Copyright} object with the given data
147      @throws NullPointerException if the {@code author} is {@code null}
148      @throws java.time.DateTimeException if the given {@code year} is invalid
149      */
150     public static Copyright of(
151         final String author,
152         final int year,
153         final URI license
154     ) {
155         return new Copyright(author, Year.of(year), license);
156     }
157 
158     /**
159      * Create a new {@code Copyright} object with the given data.
160      *
161      @param author copyright holder (TopoSoft, Inc.)
162      @param year year of copyright.
163      @param license link to external file containing license text.
164      @return a new {@code Copyright} object with the given data
165      @throws NullPointerException if the {@code author} is {@code null}
166      @throws IllegalArgumentException if the given {@code license} is not a
167      *         valid {@code URI} object
168      @throws java.time.DateTimeException if the given {@code year} is invalid
169      */
170     public static Copyright of(
171         final String author,
172         final int year,
173         final String license
174     ) {
175         return new Copyright(author, Year.of(year), parseURI(license));
176     }
177 
178     /**
179      * Create a new {@code Copyright} object with the given data.
180      *
181      @param author copyright holder (TopoSoft, Inc.)
182      @param year year of copyright.
183      @return a new {@code Copyright} object with the given data
184      @throws NullPointerException if the {@code author} is {@code null}
185      */
186     public static Copyright of(final String author, final Year year) {
187         return new Copyright(author, year, null);
188     }
189 
190     /**
191      * Create a new {@code Copyright} object with the given data.
192      *
193      @param author copyright holder (TopoSoft, Inc.)
194      @param year year of copyright.
195      @return a new {@code Copyright} object with the given data
196      @throws NullPointerException if the {@code author} is {@code null}
197      @throws java.time.DateTimeException if the given {@code year} is invalid
198      */
199     public static Copyright of(final String author, final int year) {
200         return new Copyright(author, Year.of(year)null);
201     }
202 
203     /**
204      * Create a new {@code Copyright} object with the given data.
205      *
206      @param author copyright holder (TopoSoft, Inc.)
207      @param license link to external file containing license text.
208      @return a new {@code Copyright} object with the given data
209      @throws NullPointerException if the {@code author} is {@code null}
210      */
211     public static Copyright of(final String author, final URI license) {
212         return new Copyright(author, null, license);
213     }
214 
215     /**
216      * Create a new {@code Copyright} object with the given data.
217      *
218      @param author copyright holder (TopoSoft, Inc.)
219      @return a new {@code Copyright} object with the given data
220      @throws NullPointerException if the {@code author} is {@code null}
221      */
222     public static Copyright of(final String author) {
223         return new Copyright(author, null, null);
224     }
225 
226     /* *************************************************************************
227      *  Java object serialization
228      * ************************************************************************/
229 
230     @Serial
231     private Object writeReplace() {
232         return new SerialProxy(SerialProxy.COPYRIGHT, this);
233     }
234 
235     @Serial
236     private void readObject(final ObjectInputStream stream)
237         throws InvalidObjectException
238     {
239         throw new InvalidObjectException("Serialization proxy required.");
240     }
241 
242     void write(final DataOutput outthrows IOException {
243         IO.writeString(_author, out);
244         out.writeBoolean(_year != null);
245         if (_year != nullIO.writeInt(_year.getValue(), out);
246         IO.writeNullableString(_license != null ? _license.toString() : null, out);
247     }
248 
249     static Copyright read(final DataInput inthrows IOException {
250         return new Copyright(
251             IO.readString(in),
252             in.readBoolean() ? Year.of(IO.readInt(in)) : null,
253             parseURI(IO.readNullableString(in))
254         );
255     }
256 
257     /* *************************************************************************
258      *  XML stream object serialization
259      * ************************************************************************/
260 
261     static final XMLWriter<Copyright> WRITER =  XMLWriter.elem("copyright",
262         XMLWriter.attr("author").map(cr -> cr._author),
263         XMLWriter.elem("year").map(cr -> toYearString(cr._year)),
264         XMLWriter.elem("license").map(cr -> toUriString(cr._license))
265     );
266 
267     static final XMLReader<Copyright> READER = XMLReader.elem(
268         v -> Copyright.of(
269             (String)v[0],
270             (Year)v[1],
271             (URI)v[2]
272         ),
273         "copyright",
274         XMLReader.attr("author"),
275         XMLReader.elem("year").map(Format::parseYear),
276         XMLReader.elem("license").map(Format::parseURI)
277     );
278 
279 }