/**
   * Writes record with information about particular segment (allele).
   *
   * <p>
   *
   * <p>There are two main types of such records (depending on value of {@code isReference} option):
   *
   * <p>
   *
   * <ul>
   *   <p>
   *   <li><b>Reference records (like IMGT *01 alleles).</b> Such records must have accession number
   *       of source sequence and array of reference points and must not have mutation list and
   *       reference allele fields.
   *       <p>
   *   <li><b>Allele records (other alleles).</b> Such records must have mutation list and reference
   *       allele field.
   *       <p>
   * </ul>
   *
   * <p>
   *
   * <p>Mutation positions in the mutation list ( {@code mutations} option ) must be converted to
   * positions relative to the first defined reference point of the reference allele.
   *
   * @param type type of the segment (V, D, J or C)
   * @param alleleName full name of allele (e.g. TRBV12-2*01)
   * @param isReference is it a reference allele
   * @param isFunctional {@code true} if this gene is functional; {@code false} if this gene is
   *     pseudogene
   * @param accession accession number of original (source) sequence
   * @param referencePoints array of reference points
   * @param reference allele name of the reference allele
   * @param mutations array of mutations
   * @param referenceGeneFeature reference gene feature
   * @throws java.io.IOException if an I/O error occurs.
   */
  public void writeAllele(
      GeneType type,
      String alleleName,
      boolean isReference,
      boolean isFunctional,
      String accession,
      int[] referencePoints,
      String reference,
      int[] mutations,
      GeneFeature referenceGeneFeature)
      throws IOException {
    // Validation
    if ((accession == null) != (referencePoints == null)
        || (reference == null) != (mutations == null)
        || (reference == null) != (referenceGeneFeature == null))
      throw new IllegalArgumentException();
    if (isReference && (mutations != null || accession == null))
      throw new IllegalArgumentException();
    if (mutations == null && accession == null) throw new IllegalArgumentException();

    stream.writeByte(ALLELE_TYPE);
    stream.writeByte(type.id());
    stream.writeUTF(alleleName);
    stream.writeByte(
        (isReference ? 1 : 0)
            | (isFunctional ? 2 : 0)
            | (accession != null ? 4 : 0)
            | (reference != null ? 8 : 0));

    if (accession != null) {
      if (GENE_TYPE_INFOS_WC.get(type).size != referencePoints.length)
        throw new IllegalArgumentException("Wrong number of reference points.");

      stream.writeUTF(accession);
      for (int i = 0; i < referencePoints.length; ++i) stream.writeInt(referencePoints[i]);
    }

    if (reference != null) {
      stream.writeUTF(reference);
      LociLibraryIOUtils.writeReferenceGeneFeature(stream, referenceGeneFeature);
      stream.writeInt(mutations.length);
      for (int i = 0; i < mutations.length; ++i) stream.writeInt(mutations[i]);
    }
  }
 public static GeneTypeInfo getGeneTypeInfo(GeneType geneType, boolean withFR4Correction) {
   return withFR4Correction ? GENE_TYPE_INFOS_WC.get(geneType) : GENE_TYPE_INFOS.get(geneType);
 }