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 out) throws IOException {
243 IO.writeString(_author, out);
244 out.writeBoolean(_year != null);
245 if (_year != null) IO.writeInt(_year.getValue(), out);
246 IO.writeNullableString(_license != null ? _license.toString() : null, out);
247 }
248
249 static Copyright read(final DataInput in) throws 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 }
|