001 /*
002 * Java Genetic Algorithm Library (jenetics-3.9.0).
003 * Copyright (c) 2007-2017 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@gmx.at)
019 */
020 package org.jenetics.util;
021
022 import static org.jenetics.internal.util.JAXBContextCache.context;
023 import static org.jenetics.internal.util.jaxb.adapterFor;
024 import static org.jenetics.internal.util.jaxb.marshal;
025
026 import java.io.File;
027 import java.io.FileInputStream;
028 import java.io.FileOutputStream;
029 import java.io.IOException;
030 import java.io.InputStream;
031 import java.io.ObjectInputStream;
032 import java.io.ObjectOutputStream;
033 import java.io.OutputStream;
034 import java.nio.file.Path;
035 import java.util.Arrays;
036
037 import javax.xml.bind.Marshaller;
038 import javax.xml.bind.Unmarshaller;
039 import javax.xml.bind.annotation.adapters.XmlAdapter;
040
041 import org.jenetics.internal.util.JAXBContextCache;
042 import org.jenetics.internal.util.require;
043
044 /**
045 * Class for object serialization. The following example shows how to write and
046 * reload a given population.
047 *
048 * <pre>{@code
049 * // Creating result population.
050 * EvolutionResult<DoubleGene, Double> result = stream
051 * .collect(toBestEvolutionResult());
052 *
053 * // Writing the population to disk.
054 * final File file = new File("population.xml");
055 * IO.jaxb.write(result.getPopulation(), file);
056 *
057 * // Reading the population from disk.
058 * Population<DoubleGene, Double> population =
059 * (Population<DoubleGene, Double>)IO.jaxb.read(file);
060 * EvolutionStream<DoubleGene, Double> stream = Engine
061 * .build(ff, gtf)
062 * .stream(population, 1);
063 * }</pre>
064 *
065 * The {@code jaxb} marshalling also allows to read and write own classes. For
066 * this you have to register your {@code @XmlType}d class first.
067 * <pre>{@code
068 * // The user defined 'JAXB' model class.
069 * \@XmlRootElement(name = "data-class")
070 * \@XmlType(name = "DataClass")
071 * \@XmlAccessorType(XmlAccessType.FIELD)
072 * public static final class DataClass {
073 * \@XmlAttribute public String name;
074 * \@XmlValue public String value;
075 * }
076 *
077 * // Register the 'JAXB' model class.
078 * IO.JAXB.register(DataClass.class);
079 * final DataClass data = ...;
080 * IO.jaxb.write(data, "data.xml");
081 * }</pre>
082 *
083 * It is safe to call {@code IO.JAXB.register(DataClass.class)} more than once.
084 *
085 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
086 * @since 1.0
087 * @version 3.5
088 */
089 public abstract class IO {
090
091 protected IO() {
092 }
093
094 /**
095 * Helper class for <em>JAXB</em> class registering/de-registering.
096 *
097 * <pre>{@code
098 * // The user defined 'JAXB' model class.
099 * \@XmlRootElement(name = "data-class")
100 * \@XmlType(name = "DataClass")
101 * \@XmlAccessorType(XmlAccessType.FIELD)
102 * public static final class DataClass {
103 * \@XmlAttribute public String name;
104 * \@XmlValue public String value;
105 * }
106 *
107 * // Register the 'JAXB' model class.
108 * IO.JAXB.register(DataClass.class);
109 * final DataClass data = ...;
110 * IO.jaxb.write(data, "data.xml");
111 * }</pre>
112 *
113 * It is safe to call {@code IO.JAXB.register(DataClass.class)} more than
114 * once.
115 *
116 * @deprecated Since the {@code javax.xml.bind} is marked as deprecated for
117 * removal in Java 9, the JAXB marshalling will be removed as
118 * well. Use the {@code org.jenetics.xml} module when writing
119 * and reading Jenetics data-objects as XML.
120 *
121 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
122 * @since 3.5
123 * @version 3.5
124 */
125 @Deprecated
126 public static final class JAXB {
127 private JAXB() {require.noInstance();}
128
129 /**
130 * Registers the given <em>JAXB</em> model classes. This allows to use
131 * the {@code IO.jaxb} class with own <em>JAXB</em> marshallings.
132 * <p>
133 * <em>It is safe to call this method more than once for a given class.
134 * The class is registered only once.</em>
135 *
136 * @param classes the <em>JAXB</em> model classes to register
137 * @throws NullPointerException if one of the classes is {@code null}
138 */
139 public static void register(final Class<?>... classes) {
140 Arrays.asList(classes).forEach(JAXBContextCache::add);
141 }
142
143 /**
144 * De-registers the given <em>JAXB</em> model classes.
145 *
146 * @param classes the <em>JAXB</em> model classes to register
147 * @throws NullPointerException if one of the classes is {@code null}
148 */
149 public static void deregister(final Class<?>... classes) {
150 Arrays.asList(classes).forEach(JAXBContextCache::remove);
151 }
152
153 /**
154 * Check is the given class is already registered.
155 *
156 * @param cls the class to check
157 * @return {@code true} if the given class is already registered,
158 * {@code false} otherwise.
159 */
160 public static boolean contains(final Class<?> cls) {
161 return JAXBContextCache.contains(cls);
162 }
163 }
164
165 /**
166 * JAXB for <i>XML</i> serialization.
167 *
168 * @deprecated Since the {@code javax.xml.bind} is marked as deprecated for
169 * removal in Java 9, the JAXB marshalling will be removed as
170 * well. Use the {@code org.jenetics.xml} module when writing
171 * and reading Jenetics data-objects as XML.
172 */
173 @Deprecated
174 public static final IO jaxb = new IO() {
175
176 @Override
177 public void write(final Object object, final OutputStream out)
178 throws IOException
179 {
180 try {
181 final Marshaller marshaller = context().createMarshaller();
182 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
183 marshaller.marshal(marshal(object), out);
184 } catch (Exception e) {
185 throw new IOException(e);
186 }
187 }
188
189 @Override
190 public <T> T read(final Class<T> type, final InputStream in)
191 throws IOException
192 {
193 try {
194 final Unmarshaller unmarshaller = context().createUnmarshaller();
195
196 //final XMLInputFactory factory = XMLInputFactory.newInstance();
197 //final XMLStreamReader reader = factory.createXMLStreamReader(in);
198 //try {
199 final Object object = unmarshaller.unmarshal(in);
200 final XmlAdapter<Object, Object> adapter = adapterFor(object);
201 if (adapter != null) {
202 return type.cast(adapter.unmarshal(object));
203 } else {
204 return type.cast(object);
205 }
206 //} finally {
207 // reader.close();
208 //}
209 } catch (Exception e) {
210 throw new IOException(e);
211 }
212 }
213 };
214
215 /**
216 * IO implementation for "native" <i>Java</i> serialization.
217 */
218 public static final IO object = new IO() {
219
220 @Override
221 public void write(final Object object, final OutputStream out)
222 throws IOException
223 {
224 final ObjectOutputStream oout = new ObjectOutputStream(out);
225 oout.writeObject(object);
226 out.flush();
227 }
228
229 @Override
230 public <T> T read(final Class<T> type, final InputStream in)
231 throws IOException
232 {
233 final ObjectInputStream oin = new ObjectInputStream(in);
234 try {
235 return type.cast(oin.readObject());
236 } catch (ClassNotFoundException | ClassCastException e) {
237 throw new IOException(e);
238 }
239 }
240 };
241
242
243 /**
244 * Write the (serializable) object to the given path.
245 *
246 * @param object the object to serialize.
247 * @param path the path to write the object to.
248 * @throws NullPointerException if one of the arguments is {@code null}.
249 * @throws IOException if the object could not be serialized.
250 */
251 public void write(final Object object, final String path)
252 throws IOException
253 {
254 write(object, new File(path));
255 }
256
257 /**
258 * Write the (serializable) object to the given path.
259 *
260 * @param object the object to serialize.
261 * @param path the path to write the object to.
262 * @throws NullPointerException if one of the arguments is {@code null}.
263 * @throws IOException if the object could not be serialized.
264 */
265 public void write(final Object object, final Path path)
266 throws IOException
267 {
268 write(object, path.toFile());
269 }
270
271 /**
272 * Write the (serializable) object to the given file.
273 *
274 * @param object the object to serialize.
275 * @param file the file to write the object to.
276 * @throws NullPointerException if one of the arguments is {@code null}.
277 * @throws IOException if the object could not be serialized.
278 */
279 public void write(final Object object, final File file)
280 throws IOException
281 {
282 try (final FileOutputStream out = new FileOutputStream(file)) {
283 write(object, out);
284 }
285 }
286
287 /**
288 * Write the (serializable) object to the given output stream.
289 *
290 * @param object the object to serialize.
291 * @param out the output stream to write the object to.
292 * @throws NullPointerException if one of the arguments is {@code null}.
293 * @throws IOException if the object could not be serialized.
294 */
295 public abstract void write(final Object object, final OutputStream out)
296 throws IOException;
297
298 /**
299 * Reads an object from the given file.
300 *
301 * @param <T> the type of the read object
302 * @param path the path to read from.
303 * @param type the type of the read object.
304 * @return the de-serialized object.
305 * @throws NullPointerException if the input stream {@code in} is {@code null}.
306 * @throws IOException if the object could not be read.
307 */
308 public <T> T read(final Class<T> type, final String path)
309 throws IOException
310 {
311 try (final FileInputStream in = new FileInputStream(new File(path))) {
312 return read(type, in);
313 }
314 }
315
316 /**
317 * Reads an object from the given file.
318 *
319 * @param path the path to read from.
320 * @return the de-serialized object.
321 * @throws NullPointerException if the input stream {@code in} is {@code null}.
322 * @throws IOException if the object could not be read.
323 */
324 public Object read(final String path) throws IOException {
325 return read(Object.class, path);
326 }
327
328 /**
329 * Reads an object from the given file.
330 *
331 * @param <T> the type of the read object
332 * @param path the path to read from.
333 * @param type the type of the read object.
334 * @return the de-serialized object.
335 * @throws NullPointerException if the input stream {@code in} is {@code null}.
336 * @throws IOException if the object could not be read.
337 */
338 public <T> T read(final Class<T> type, final Path path)
339 throws IOException
340 {
341 try (final FileInputStream in = new FileInputStream(path.toFile())) {
342 return read(type, in);
343 }
344 }
345
346 /**
347 * Reads an object from the given file.
348 *
349 * @param path the path to read from.
350 * @return the de-serialized object.
351 * @throws NullPointerException if the input stream {@code in} is {@code null}.
352 * @throws IOException if the object could not be read.
353 */
354 public Object read(final Path path) throws IOException {
355 return read(Object.class, path);
356 }
357
358 /**
359 * Reads an object from the given file.
360 *
361 * @param <T> the type of the read object
362 * @param file the file to read from.
363 * @param type the type of the read object.
364 * @return the de-serialized object.
365 * @throws NullPointerException if the input stream {@code in} is {@code null}.
366 * @throws IOException if the object could not be read.
367 */
368 public <T> T read(final Class<T> type, final File file)
369 throws IOException
370 {
371 try (final FileInputStream in = new FileInputStream(file)) {
372 return read(type, in);
373 }
374 }
375
376 /**
377 * Reads an object from the given file.
378 *
379 * @param file the file to read from.
380 * @return the de-serialized object.
381 * @throws NullPointerException if the input stream {@code in} is {@code null}.
382 * @throws IOException if the object could not be read.
383 */
384 public Object read(final File file) throws IOException {
385 return read(Object.class, file);
386 }
387
388 /**
389 * Reads an object from the given input stream.
390 *
391 * @param <T> the type of the read object
392 * @param in the input stream to read from.
393 * @param type the type of the read object.
394 * @return the de-serialized object.
395 * @throws NullPointerException if the input stream {@code in} is {@code null}.
396 * @throws IOException if the object could not be read.
397 */
398 public abstract <T> T read(final Class<T> type, final InputStream in)
399 throws IOException;
400
401 /**
402 * Reads an object from the given input stream.
403 *
404 * @param in the input stream to read from.
405 * @return the de-serialized object.
406 * @throws NullPointerException if the input stream {@code in} is {@code null}.
407 * @throws IOException if the object could not be read.
408 */
409 public Object read(final InputStream in) throws IOException {
410 return read(Object.class, in);
411 }
412 }
|