Readers.java
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.xml;
021 
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static org.jenetics.xml.stream.Reader.attr;
025 import static org.jenetics.xml.stream.Reader.elem;
026 import static org.jenetics.xml.stream.Reader.elems;
027 import static org.jenetics.xml.stream.Reader.text;
028 
029 import java.io.InputStream;
030 import java.util.List;
031 import java.util.function.Function;
032 import java.util.function.IntFunction;
033 import java.util.stream.Stream;
034 
035 import javax.xml.stream.XMLStreamException;
036 
037 import org.jenetics.BoundedGene;
038 import org.jenetics.Chromosome;
039 import org.jenetics.DoubleGene;
040 import org.jenetics.EnumGene;
041 import org.jenetics.Gene;
042 import org.jenetics.IntegerGene;
043 import org.jenetics.LongGene;
044 import org.jenetics.util.CharSeq;
045 import org.jenetics.util.ISeq;
046 import org.jenetics.util.MSeq;
047 import org.jenetics.xml.stream.AutoCloseableXMLStreamReader;
048 import org.jenetics.xml.stream.Reader;
049 import org.jenetics.xml.stream.XML;
050 
051 /**
052  * This class contains static fields and methods, for creating chromosome- and
053  * genotype readers for different gene types.
054  *
055  <pre>{@code
056  * final Reader<Genotype<BitGene> bgr =
057  *     Readers.Genotype.reader(Readers.BitChromosome.reader()));
058  *
059  * final Reader<Genotype<IntegerGene>> igr =
060  *     Writers.Genotype.reader(Readers.IntegerChromosome.reader()));
061  *
062  * final Reader<Genotype<DoubleGene>> dgr =
063  *     Readers.Genotype.reader(Readers.DoubleChromosome.reader()));
064  * }</pre>
065  *
066  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
067  @version 3.9
068  @since 3.9
069  */
070 public final class Readers {
071     private Readers() {}
072 
073     /**
074      * Bit chromosome reader methods, which reads XML-representations of
075      * bit-chromosomes.
076      <p>
077      <b>XML</b>
078      <pre> {@code
079      <bit-chromosome length="20" ones-probability="0.5">11100011101011001010</bit-chromosome>
080      * }</pre>
081      * }
082      */
083     public static final class BitChromosome {
084         private BitChromosome() {}
085 
086         /**
087          * Return a XML reader for {@link org.jenetics.BitChromosome} objects.
088          *
089          @return a chromosome reader
090          */
091         public static Reader<org.jenetics.BitChromosome> reader() {
092             return elem(
093                 v -> org.jenetics.BitChromosome.of(
094                     (String)v[2](int)v[0](double)v[1]
095                 ),
096                 Writers.BitChromosome.ROOT_NAME,
097                 attr(Writers.BitChromosome.LENGTH_NAME)
098                     .map(Integer::parseInt),
099                 attr(Writers.BitChromosome.ONES_PROBABILITY_NAME)
100                     .map(Double::parseDouble),
101                 text()
102             );
103         }
104 
105         /**
106          * Read a new {@link org.jenetics.BitChromosome} from the given input
107          * stream.
108          *
109          @param in the data source of the bit-chromosome
110          @return the bit-chromosome read from the input stream
111          @throws XMLStreamException if reading the chromosome fails
112          @throws NullPointerException if the given input stream is {@code null}
113          */
114         public static org.jenetics.BitChromosome read(final InputStream in)
115             throws XMLStreamException
116         {
117             try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
118                 xml.next();
119                 return reader().read(xml);
120             }
121         }
122     }
123 
124     /**
125      * Reader methods for {@link org.jenetics.CharacterChromosome} objects.
126      <p>
127      <b>XML format</b>
128      <pre> {@code
129      <character-chromosome length="4">
130      *     <valid-alleles>ABCDEFGHIJKLMNOPQRSTUVWXYZ<valid-alleles>
131      *     <alleles>ASDF</alleles>
132      </character-chromosome>
133      * }</pre>
134      */
135     public static final class CharacterChromosome {
136         private CharacterChromosome() {}
137 
138         /**
139          * Return a XML reader for {@link org.jenetics.CharacterChromosome}
140          * objects.
141          *
142          @return a chromosome reader
143          */
144         public static Reader<org.jenetics.CharacterChromosome> reader() {
145             return elem(
146                 v -> org.jenetics.CharacterChromosome.of(
147                     (String)v[2](CharSeq)v[1]
148                 ),
149                 Writers.CharacterChromosome.ROOT_NAME,
150                 attr(Writers.CharacterChromosome.LENGTH_NAME)
151                     .map(Integer::parseInt),
152                 elem(Writers.CharacterChromosome.VALID_ALLELES_NAME,
153                     text().map(CharSeq::new)),
154                 elem(Writers.CharacterChromosome.ALLELES_NAME, text())
155             );
156         }
157 
158         /**
159          * Read a new {@link org.jenetics.CharacterChromosome} from the given
160          * input stream.
161          *
162          @param in the data source of the chromosome
163          @return the bit-chromosome read from the input stream
164          @throws XMLStreamException if reading the chromosome fails
165          @throws NullPointerException if the given input stream is {@code null}
166          */
167         public static org.jenetics.CharacterChromosome read(final InputStream in)
168             throws XMLStreamException
169         {
170             try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
171                 xml.next();
172                 return reader().read(xml);
173             }
174         }
175 
176     }
177 
178     /**
179      * Reader methods for {@link org.jenetics.BoundedChromosome} objects.
180      <p>
181      <b>XML format</b>
182      <pre> {@code
183      <root-name length="3">
184      *     <min>aaa</min>
185      *     <max>zzz</max>
186      *     <alleles>
187      *         <allele>iii</allele>
188      *         <allele>fff</allele>
189      *         <allele>ggg</allele>
190      *     </alleles>
191      </root-name>
192      * }</pre>
193      */
194     public static final class BoundedChromosome {
195         private BoundedChromosome() {}
196 
197         /**
198          * Create a bounded chromosome reader with the given configuration.
199          *
200          @param name the root element name
201          @param gene the gene creator
202          @param genes the gene array creator
203          @param chromosome the chromosome creator
204          @param alleleReader the allele reader
205          @param <A> the allele type
206          @param <G> the gene type
207          @param <C> the chromosome type
208          @return a bounded chromosome reader
209          @throws NullPointerException if one of the arguments is {@code null}
210          */
211         public static <
212             extends Comparable<? super A>,
213             extends BoundedGene<A, G>,
214             extends org.jenetics.BoundedChromosome<A, G>
215         >
216         Reader<C> reader(
217             final String name,
218             final BoundedGeneCreator<A, G> gene,
219             final IntFunction<G[]> genes,
220             final Function<G[], C> chromosome,
221             final Reader<? extends A> alleleReader
222         ) {
223             return elem(v -> {
224                 final int length = (int)v[0];
225                 @SuppressWarnings("unchecked")
226                 final A min = (A)v[1];
227                 @SuppressWarnings("unchecked")
228                 final A max = (A)v[2];
229                 @SuppressWarnings("unchecked")
230                 final List<A> alleles = (List<A>)v[3];
231 
232                 if (alleles.size() != length) {
233                     throw new IllegalArgumentException(format(
234                         "Expected %d alleles, but got %d,",
235                         length, alleles.size()
236                     ));
237                 }
238 
239                 return chromosome.apply(
240                     alleles.stream()
241                         .map(value -> gene.create(value, min, max))
242                         .toArray(genes)
243                 );
244             }, name,
245                 attr(Writers.BoundedChromosome.LENGTH_NAME).map(Integer::parseInt),
246                 elem(Writers.BoundedChromosome.MIN_NAME, alleleReader),
247                 elem(Writers.BoundedChromosome.MAX_NAME, alleleReader),
248                 elem(Writers.BoundedChromosome.ALLELES_NAME,
249                     elems(elem(Writers.BoundedChromosome.ALLELE_NAME, alleleReader))
250                 )
251             );
252         }
253 
254     }
255 
256     /**
257      * Reader methods for {@link org.jenetics.IntegerChromosome} objects.
258      <p>
259      <b>XML format</b>
260      <pre> {@code
261      <int-chromosome length="3">
262      *     <min>-2147483648</min>
263      *     <max>2147483647</max>
264      *     <alleles>
265      *         <allele>-1878762439</allele>
266      *         <allele>-957346595</allele>
267      *         <allele>-88668137</allele>
268      *     </alleles>
269      </int-chromosome>
270      * }</pre>
271      */
272     public static final class IntegerChromosome {
273         private IntegerChromosome() {}
274 
275         /**
276          * Return the default allele reader for the {@code IntegerChromosome}.
277          *
278          @return the default allele reader
279          */
280         public static Reader<Integer> alleleReader() {
281             return text().map(Integer::parseInt);
282         }
283 
284         /**
285          * Return a {@link org.jenetics.IntegerChromosome} reader.
286          *
287          @return a integer chromosome reader
288          */
289         public static Reader<org.jenetics.IntegerChromosome> reader() {
290             return BoundedChromosome.reader(
291                 Writers.IntegerChromosome.ROOT_NAME,
292                 IntegerGene::of,
293                 IntegerGene[]::new,
294                 org.jenetics.IntegerChromosome::of,
295                 alleleReader()
296             );
297         }
298 
299         /**
300          * Read a new {@link org.jenetics.IntegerChromosome} from the given
301          * input stream.
302          *
303          @param in the data source of the chromosome
304          @return a new chromosome
305          @throws XMLStreamException if reading the chromosome fails
306          @throws NullPointerException if the given input stream is {@code null}
307          */
308         public static org.jenetics.IntegerChromosome read(final InputStream in)
309             throws XMLStreamException
310         {
311             try (AutoCloseableXMLStreamReader reader = XML.reader(in)) {
312                 reader.next();
313                 return reader().read(reader);
314             }
315         }
316 
317     }
318 
319     /**
320      * Reader methods for {@link org.jenetics.LongChromosome} objects.
321      <p>
322      <b>XML format</b>
323      <pre> {@code
324      <long-chromosome length="3">
325      *     <min>-9223372036854775808</min>
326      *     <max>9223372036854775807</max>
327      *     <alleles>
328      *         <allele>-1345217698116542402</allele>
329      *         <allele>-7144755673073475303</allele>
330      *         <allele>6053786736809578435</allele>
331      *     </alleles>
332      </long-chromosome>
333      * }</pre>
334      */
335     public static final class LongChromosome {
336         private LongChromosome() {}
337 
338         /**
339          * Return the default allele reader for the {@code LongChromosome}.
340          *
341          @return the default allele reader
342          */
343         public static Reader<Long> alleleReader() {
344             return text().map(Long::parseLong);
345         }
346 
347         /**
348          * Return a {@link org.jenetics.LongChromosome} reader.
349          *
350          @return a long chromosome reader
351          */
352         public static Reader<org.jenetics.LongChromosome> reader() {
353             return BoundedChromosome.reader(
354                 Writers.LongChromosome.ROOT_NAME,
355                 LongGene::of,
356                 LongGene[]::new,
357                 org.jenetics.LongChromosome::of,
358                 alleleReader()
359             );
360         }
361 
362         /**
363          * Read a new {@link org.jenetics.LongChromosome} from the given
364          * input stream.
365          *
366          @param in the data source of the chromosome
367          @return a new chromosome
368          @throws XMLStreamException if reading the chromosome fails
369          @throws NullPointerException if the given input stream is {@code null}
370          */
371         public static org.jenetics.LongChromosome read(final InputStream in)
372             throws XMLStreamException
373         {
374             try (AutoCloseableXMLStreamReader reader = XML.reader(in)) {
375                 reader.next();
376                 return reader().read(reader);
377             }
378         }
379 
380     }
381 
382     /**
383      * Reader methods for {@link org.jenetics.DoubleChromosome} objects.
384      <p>
385      <b>XML format</b>
386      <pre> {@code
387      <double-chromosome length="3">
388      *     <min>0.0</min>
389      *     <max>1.0</max>
390      *     <alleles>
391      *         <allele>0.27251556008507416</allele>
392      *         <allele>0.003140816229067145</allele>
393      *         <allele>0.43947528327497376</allele>
394      *     </alleles>
395      </double-chromosome>
396      * }</pre>
397      */
398     public static final class DoubleChromosome {
399         private DoubleChromosome() {}
400 
401         /**
402          * Return the default allele reader for the {@code DoubleChromosome}.
403          *
404          @return the default allele reader
405          */
406         public static Reader<Double> alleleReader() {
407             return text().map(Double::parseDouble);
408         }
409 
410         /**
411          * Return a {@link org.jenetics.DoubleChromosome} reader.
412          *
413          @return a double chromosome reader
414          */
415         public static Reader<org.jenetics.DoubleChromosome> reader() {
416             return BoundedChromosome.reader(
417                 Writers.DoubleChromosome.ROOT_NAME,
418                 DoubleGene::of,
419                 DoubleGene[]::new,
420                 org.jenetics.DoubleChromosome::of,
421                 alleleReader()
422             );
423         }
424 
425         /**
426          * Read a new {@link org.jenetics.DoubleChromosome} from the given
427          * input stream.
428          *
429          @param in the data source of the chromosome
430          @return a new chromosome
431          @throws XMLStreamException if reading the chromosome fails
432          @throws NullPointerException if the given input stream is {@code null}
433          */
434         public static org.jenetics.DoubleChromosome read(final InputStream in)
435             throws XMLStreamException
436         {
437             try (AutoCloseableXMLStreamReader reader = XML.reader(in)) {
438                 reader.next();
439                 return reader().read(reader);
440             }
441         }
442 
443     }
444 
445     /**
446      * Reader methods for {@link org.jenetics.PermutationChromosome} objects.
447      <p>
448      <b>XML format</b>
449      <pre> {@code
450      <permutation-chromosome length="5">
451      *     <valid-alleles type="java.lang.Integer">
452      *         <allele>0</allele>
453      *         <allele>1</allele>
454      *         <allele>2</allele>
455      *         <allele>3</allele>
456      *         <allele>4</allele>
457      *     </valid-alleles>
458      *     <order>2 1 3 5 4</order>
459      </permutation-chromosome>
460      * }</pre>
461      */
462     public static final class PermutationChromosome {
463         private PermutationChromosome() {}
464 
465         /**
466          * Return a reader for permutation chromosomes with the given allele
467          * reader.
468          *
469          @param alleleReader the allele reader
470          @param <A> the allele type
471          @return a permutation chromosome reader
472          @throws NullPointerException if the given allele reader is
473          *        {@code null}
474          */
475         public static <A> Reader<org.jenetics.PermutationChromosome<A>>
476         reader(final Reader<? extends A> alleleReader) {
477             requireNonNull(alleleReader);
478 
479             return elem(v -> {
480                 final int length = (int)v[0];
481                 @SuppressWarnings("unchecked")
482                 final ISeq<A> validAlleles = ISeq.of((List<A>)v[1]);
483 
484                 final int[] order = Stream.of(((Stringv[2]).split("\\s"))
485                     .mapToInt(Integer::parseInt)
486                     .toArray();
487 
488                 final MSeq<EnumGene<A>> alleles = MSeq.ofLength(length);
489                 for (int i = 0; i < length; ++i) {
490                     final EnumGene<A> gene = EnumGene.of(order[i], validAlleles);
491                     alleles.set(i, gene);
492                 }
493 
494                 return new org.jenetics.PermutationChromosome<A>(alleles.toISeq());
495             },
496                 Writers.PermutationChromosome.ROOT_NAME,
497                 attr(Writers.PermutationChromosome.LENGTH_NAME).map(Integer::parseInt),
498                 elem(Writers.PermutationChromosome.VALID_ALLELES_NAME,
499                     elems(elem(Writers.PermutationChromosome.ALLELE_NAME, alleleReader))
500                 ),
501                 elem(Writers.PermutationChromosome.ORDER_NAME, text())
502             );
503         }
504 
505         /**
506          * Reads a new {@link org.jenetics.PermutationChromosome} from the given
507          * input stream.
508          *
509          @param <A> the allele type
510          @param in the data source of the chromosome
511          @param alleleReader the allele reader
512          @return a new permutation chromosome
513          @throws XMLStreamException if reading the chromosome fails
514          @throws NullPointerException if one of the arguments is {@code null}
515          */
516         public static <A> org.jenetics.PermutationChromosome<A>
517         read(final InputStream in, final Reader<? extends A> alleleReader)
518             throws XMLStreamException
519         {
520             requireNonNull(alleleReader);
521             requireNonNull(in);
522 
523             try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
524                 xml.next();
525                 return reader(alleleReader).read(xml);
526             }
527         }
528 
529     }
530 
531     /**
532      * Writer methods for {@link org.jenetics.Genotype} objects.
533      <p>
534      <b>XML format</b>
535      <pre> {@code
536      <genotype length="2" ngenes="5">
537      *     <double-chromosome length="3">
538      *         <min>0.0</min>
539      *         <max>1.0</max>
540      *         <alleles>
541      *             <allele>0.27251556008507416</allele>
542      *             <allele>0.003140816229067145</allele>
543      *             <allele>0.43947528327497376</allele>
544      *         </alleles>
545      *     </double-chromosome>
546      *     <double-chromosome length="2">
547      *         <min>0.0</min>
548      *         <max>1.0</max>
549      *         <alleles>
550      *             <allele>0.4026521545744768</allele>
551      *             <allele>0.36137605952663554</allele>
552      *         <alleles>
553      *     </double-chromosome>
554      </genotype>
555      * }</pre>
556      */
557     public static final class Genotype {
558         private Genotype() {}
559 
560         /**
561          * Create a genotype reader with he given chromosome reader.
562          *
563          @param chromosomeReader the underlying chromosome reader
564          @param <A> the allele type
565          @param <G> the gene type
566          @param <C> the chromosome type
567          @return a genotype reader with he given chromosome reader
568          @throws NullPointerException if the given {@code chromosomeReader} is
569          *         {@code null}
570          */
571         public static <
572             A,
573             extends Gene<A, G>,
574             extends Chromosome<G>
575         >
576         Reader<org.jenetics.Genotype<G>>
577         reader(final Reader<? extends C> chromosomeReader) {
578             requireNonNull(chromosomeReader);
579 
580             return elem(v -> {
581                 @SuppressWarnings("unchecked")
582                 final List<C> chromosomes = (List<C>)v[2];
583                 final org.jenetics.Genotype<G> genotype =
584                     org.jenetics.Genotype.of(chromosomes);
585 
586                 final int length = (int)v[0];
587                 final int ngenes = (int)v[1];
588                 if (length != genotype.length()) {
589                     throw new IllegalArgumentException(format(
590                         "Expected %d chromosome, but read %d.",
591                         length, genotype.length()
592                     ));
593                 }
594                 if (ngenes != genotype.getNumberOfGenes()) {
595                     throw new IllegalArgumentException(format(
596                         "Expected %d genes, but read %d.",
597                         ngenes, genotype.getNumberOfGenes()
598                     ));
599                 }
600 
601                 return genotype;
602             },
603                 Writers.Genotype.ROOT_NAME,
604                 attr(Writers.Genotype.LENGTH_NAME).map(Integer::parseInt),
605                 attr(Writers.Genotype.NGENES_NAME).map(Integer::parseInt),
606                 elems(chromosomeReader)
607             );
608         }
609 
610         /**
611          * Reads a genotype by using the given chromosome reader.
612          *
613          @param <A> the allele type
614          @param <G> the gene type
615          @param <C> the chromosome type
616          @param in the input stream to read the genotype from
617          @param chromosomeReader the used chromosome reader
618          @return a genotype by using the given chromosome reader
619          @throws XMLStreamException if reading the genotype fails
620          @throws NullPointerException if one of the arguments is {@code null}
621          */
622         public static <
623             A,
624             extends Gene<A, G>,
625             extends Chromosome<G>
626         >
627         org.jenetics.Genotype<G>
628         read(final InputStream in, final Reader<? extends C> chromosomeReader)
629             throws XMLStreamException
630         {
631             requireNonNull(chromosomeReader);
632             requireNonNull(in);
633 
634             try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
635                 xml.next();
636                 return reader(chromosomeReader).read(xml);
637             }
638         }
639     }
640 
641     /**
642      * This class contains static reader methods for
643      {@link org.jenetics.Genotype} objects.
644      <p>
645      <b>XML format</b>
646      <pre> {@code
647      <genotypes length="1">
648      *     <genotype length="2" ngenes="5">
649      *         <double-chromosome length="3">
650      *             <min>0.0</min>
651      *             <max>1.0</max>
652      *             <alleles>
653      *                 <allele>0.27251556008507416</allele>
654      *                 <allele>0.003140816229067145</allele>
655      *                 <allele>0.43947528327497376</allele>
656      *             </alleles>
657      *         </double-chromosome>
658      *         <double-chromosome length="2">
659      *             <min>0.0</min>
660      *             <max>1.0</max>
661      *             <alleles>
662      *                 <allele>0.4026521545744768</allele>
663      *                 <allele>0.36137605952663554</allele>
664      *             <alleles>
665      *         </double-chromosome>
666      *     </genotype>
667      </genotypes>
668      * }</pre>
669      */
670     public static final class Genotypes {
671         private Genotypes() {}
672 
673         /**
674          * Return a genotypes reader using the given chromosome reader.
675          *
676          @param chromosomeReader the underlying chromosome reader
677          @param <A> the allele type
678          @param <G> the gene type
679          @param <C> the chromosome type
680          @return a genotypes reader using the given chromosome reader
681          @throws NullPointerException if the given {@code chromosomeReader} is
682          *         {@code null}
683          */
684         @SuppressWarnings("unchecked")
685         public static <
686             A,
687             extends Gene<A, G>,
688             extends Chromosome<G>
689         >
690         Reader<List<org.jenetics.Genotype<G>>>
691         reader(final Reader<C> chromosomeReader) {
692             return elem(
693                 p -> (List<org.jenetics.Genotype<G>>)p[0],
694                 Writers.Genotypes.ROOT_NAME,
695                 elems(Genotype.reader(chromosomeReader))
696             );
697         }
698 
699         /**
700          * Reads the genotypes by using the given chromosome reader.
701          *
702          @param <A> the allele type
703          @param <G> the gene type
704          @param <C> the chromosome type
705          @param in the input stream to read the genotype from
706          @param chromosomeReader the used chromosome reader
707          @return a genotype by using the given chromosome reader
708          @throws XMLStreamException if reading the genotype fails
709          @throws NullPointerException if one of the arguments is {@code null}
710          */
711         public static <
712             A,
713             extends Gene<A, G>,
714             extends Chromosome<G>
715         >
716         List<org.jenetics.Genotype<G>>
717         read(final InputStream in, final Reader<? extends C> chromosomeReader)
718             throws XMLStreamException
719         {
720             requireNonNull(chromosomeReader);
721             requireNonNull(in);
722 
723             try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
724                 xml.next();
725                 return reader(chromosomeReader).read(xml);
726             }
727         }
728 
729     }
730 
731     /**
732      * Reads the genotypes by using the given chromosome reader.
733      *
734      @see Genotypes#read(InputStream, Reader)
735      *
736      @param <A> the allele type
737      @param <G> the gene type
738      @param <C> the chromosome type
739      @param in the input stream to read the genotype from
740      @param chromosomeReader the used chromosome reader
741      @return a genotype by using the given chromosome reader
742      @throws XMLStreamException if reading the genotype fails
743      @throws NullPointerException if one of the arguments is {@code null}
744      */
745     public static <
746         A,
747         extends Gene<A, G>,
748         extends Chromosome<G>
749     >
750     List<org.jenetics.Genotype<G>>
751     read(final InputStream in, final Reader<? extends C> chromosomeReader)
752         throws XMLStreamException
753     {
754         return Genotypes.read(in, chromosomeReader);
755     }
756 
757 }