/********************************************************************************
 * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 ********************************************************************************/

package org.eclipse.mdm.openatfx.mdf.mdf4;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;

import org.asam.ods.AoException;
import org.asam.ods.ApplicationElement;
import org.asam.ods.ApplicationRelation;
import org.asam.ods.ErrorCode;
import org.asam.ods.InstanceElement;
import org.asam.ods.NameValueUnit;
import org.asam.ods.SeverityFlag;
import org.asam.ods.TS_Union;
import org.asam.ods.TS_Value;
import org.asam.ods.T_ExternalReference;
import org.eclipse.mdm.openatfx.mdf.ConvertException;
import org.eclipse.mdm.openatfx.mdf.util.BitInputStream;
import org.eclipse.mdm.openatfx.mdf.util.ConfigurationHelper;
import org.eclipse.mdm.openatfx.mdf.util.FileUtil;
import org.eclipse.mdm.openatfx.mdf.util.LookupTableHelper;
import org.eclipse.mdm.openatfx.mdf.util.ODSHelper;
import org.eclipse.mdm.openatfx.mdf.util.ODSInsertStatement;
import org.eclipse.mdm.openatfx.mdf.util.ODSModelCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Main class for writing the MDF4 file content into an ASAM ODS session backed
 * by an ATFX file.
 *
 * @author Christian Rechner
 */
public class AoSessionWriter
{
  private static final Logger LOG = LoggerFactory.getLogger(AoSessionWriter.class);
  private static final int FLAGS_BUFFER_SIZE = 1_000_000;
  private static final int MAX_RECORDS_PER_FLAGS_READ = 1000;
  private static final String ENDING_TEXTTABLE = ".texttable";
  private static final String ENDING_LINEAR = ".linear";

  /** The number format having 5 digits used for count formatting */
  private final NumberFormat countFormat;

  /** The XML parser object used for parsing the embedded XML contents */
  private final MDF4XMLParser xmlParser;

  /** helper class for lookup tables */
  private final LookupTableHelper lookupTableHelper;

  /** helper class for previews */
  private PreviewHelper previewHelper;

  // Properties
  // replace channel name characters '[' with '{' and ']' with '}'
  private boolean replaceSquareBrackets; // default = false
  // whether to use the file name as AoMeasurement name, if false, property
  // value of 'result_name' is used
  private boolean useFileNameAsResultName = true; // default = true
  // the name of the created AoMeasurement (only used if
  // use_file_name_as_result_name=false)
  private String resultName = "Messdaten"; // default = "Messdaten"
  // the name suffix of the created AoMeasurement, e.g. if suffix='_123' then
  // 'test.mf4' will be converted to 'test_123.mf4'
  private String resultSuffix = ""; // default = null
  // the mimetype of the created AoMeasurement
  private String resultMimeType = "application/x-asam.aomeasurement.timeseries"; // default
  // =
  // "application/x-asam.aomeasurement.timeseries"
  // whether to add a reference to the original file to the AoMeasurement
  // instance
  private boolean addMDF3FileAsResultAttachment; // default = false
  private boolean skipScaleConversionChannels = false;
  private boolean skipUINT64Channels = false;
  // skip channels with DT_BYTESTR
  // remove this once it is save to import channels with byte stream data
  @Deprecated
  private boolean skipByteStreamChannels = false;

  private boolean writeFlagsFile = true;
  private Path flagFile = null;

  private boolean readOnlyHeader = false;
  private Path customRatConfPath;

  // skip empty channels
  private boolean skipEmptyChannels = false;
  private boolean skipExtraConversionChannels = false;
  private boolean ignoreUnsupportedConversionTypes = false;
  private boolean skipPreviews = true;

  private boolean attachLinks2Tsts = false;
  private boolean copyToSub = false;
  private boolean ignoreATBLOCKs = false;

  private Map<Long, Long> arraySubMatrixIDsByNrOfValues = new HashMap<>();

  /**
   * Constructor.
   */
  public AoSessionWriter()
  {
    xmlParser = new MDF4XMLParser();
    countFormat = new DecimalFormat("00000");
    lookupTableHelper = new LookupTableHelper();
    previewHelper = new PreviewHelper();
  }

  /**
   * Appends the content of the MDF4 file to the ASAM ODS session.
   *
   * @param modelCache
   *        The application model cache.
   * @param idBlock
   *        The IDBLOCK.
   * @param props
   *        Map with additional attributes to be set.
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  public void writeTst(ODSModelCache modelCache, IDBLOCK idBlock, Properties props) throws AoException, IOException
  {
    Path fileName = idBlock.getMdfFilePath().getFileName();
    if (fileName == null)
    {
      throw new IOException("Unable to obtain file name!");
    }

    try
    {
      if (props != null)
      {
        // replace channel name characters '[' with '{' and ']' with '}'
        if (props.containsKey("replace_square_brackets"))
        {
          // default = false
          replaceSquareBrackets = Boolean.valueOf(props.getProperty("replace_square_brackets"));
        }
        // whether to use the file name as AoMeasurement name, if false,
        // property value of 'result_name' is used
        if (props.containsKey("use_file_name_as_result_name"))
        {
          // default = true
          useFileNameAsResultName = Boolean.valueOf(props.getProperty("use_file_name_as_result_name"));
        }
        // the name of the created AoMeasurement (only used if
        // use_file_name_as_result_name=false)
        if (props.containsKey("result_name"))
        {
          // default = Messdaten
          resultName = props.getProperty("result_name");
        }
        // the name suffix of the created AoMeasurement, e.g. if
        // suffix='_123' then 'test.mf4' will be converted to
        // 'test_123.mf4'
        if (props.containsKey("result_suffix"))
        {
          // default = null
          resultSuffix = props.getProperty("result_suffix");
        }
        // the mimetype of the created AoMeasurement
        if (props.containsKey("result_mimetype"))
        {
          // default = application/x-asam.aomeasurement.timeseries
          resultMimeType = props.getProperty("result_mimetype");
        }
        // whether to add a reference to the original file to the
        // AoMeasurement instance
        if (props.containsKey("attach_source_files"))
        {
          // default = false
          addMDF3FileAsResultAttachment = Boolean.valueOf(props.getProperty("attach_source_files"));
        }
        if (props.containsKey("read_only_header"))
        {
          readOnlyHeader = Boolean.valueOf(props.getProperty("read_only_header"));
        }
        if (props.containsKey("skip_scale_conversion_channels"))
        {
          skipScaleConversionChannels = Boolean.valueOf(props.getProperty("skip_scale_conversion_channels"));
        }
        if (props.containsKey("skip_uint64_data_channels"))
        {
          skipUINT64Channels = Boolean.valueOf(props.getProperty("skip_uint64_data_channels"));
        }
        if (props.containsKey("skip_byte_stream_channels"))
        {
          skipByteStreamChannels = Boolean.valueOf(props.getProperty("skip_byte_stream_channels"));
        }
        if (props.containsKey("write_flags_file"))
        {
          writeFlagsFile = Boolean.valueOf(props.getProperty("write_flags_file"));
        }
        if (props.containsKey("skip_empty_channels"))
        {
          skipEmptyChannels = Boolean.valueOf(props.getProperty("skip_empty_channels"));
        }
        if (props.containsKey("attachments_to_tst"))
        {
          attachLinks2Tsts = Boolean.valueOf(props.getProperty("attachments_to_tst"));
        }
        if (props.containsKey("export_to_subfolder"))
        {
          copyToSub = Boolean.valueOf(props.getProperty("export_to_subfolder"));
        }
        if (props.containsKey("$${ignore_attachments}"))
        {
          ignoreATBLOCKs = Boolean.valueOf(props.getProperty("$${ignore_attachments}"));
        }
        if (props.containsKey("comment_replacement_strings")) {
          String replacementStrings = props.getProperty("comment_replacement_strings");
          ConfigurationHelper configHelper = ConfigurationHelper.getInstance();
          configHelper.readReplacementsFromConfiguredString(replacementStrings);
        }
        if (props.containsKey("skip_extra_conversion_channels")) {
          skipExtraConversionChannels = Boolean.valueOf(props.getProperty("skip_extra_conversion_channels"));
        }
        if (props.containsKey("ignore_unsupported_conversion_types")) {
          ignoreUnsupportedConversionTypes = Boolean.valueOf(props.getProperty("ignore_unsupported_conversion_types"));
        }
        if (props.containsKey("skip_previews")) {
          skipPreviews = Boolean.valueOf(props.getProperty("skip_previews"));
        }
      }

      ODSInsertStatement ins = new ODSInsertStatement(modelCache, "tst");
      ins.setStringVal("iname", FileUtil.stripExtension(fileName.toString()));

      ins.setStringVal("mdf_file_id", idBlock.getIdFile());
      ins.setStringVal("mdf_version_str", idBlock.getIdVers());
      ins.setLongVal("mdf_version", idBlock.getIdVer());
      ins.setStringVal("mdf_program", idBlock.getIdProg());
      ins.setLongVal("mdf_unfin_flags", idBlock.getIdUnfinFlags());
      ins.setLongVal("mdf_custom_unfin_flags", idBlock.getIdCustomUnfinFlags());

      // write properties
      if (props != null)
      {
        MDF4Util.writeProperites(ins, props);
      }

      // set Relations, to environment
      ins.setLongLongVal("env", 1L);

      long iidTst = ins.execute();

      previewHelper.setCache(modelCache);
      previewHelper.setWriter(this);

      // write 'AoMeasurement' instance
      writeMea(modelCache, iidTst, idBlock);
    }
    catch (AoException | IOException e)
    {
      // make sure file with manually calculated values is deleted in case
      // of errors
      if (customRatConfPath != null && Files.exists(customRatConfPath))
      {
        try
        {
          Files.delete(customRatConfPath);
        }
        catch (IOException e2)
        {
          LOG.warn("failed to delete file with manually calculated values: '" + customRatConfPath + "'", e2);
        }
      }

      if (flagFile != null && Files.exists(flagFile))
      {
        try
        {
          Files.delete(flagFile);
        }
        catch (IOException e2)
        {
          LOG.warn("failed to delete file with exported flags: '" + flagFile + "'", e2);
        }
      }

      // preserve origin error
      throw e;
    }
  }

  /**
   * Appends the content of the MDF4 file to the ASAM ODS session.
   *
   * @param modelCache
   *        The application model cache.
   * @param ieTst
   *        The parent 'AoTest' instance.
   * @param idBlock
   *        The IDBLOCK.
   * @return The created AoMeasurement instance.
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  private void writeMea(ODSModelCache modelCache, long iidTst, IDBLOCK idBlock) throws AoException, IOException
  {
    Path fileName = idBlock.getMdfFilePath().getFileName();
    if (fileName == null)
    {
      throw new IOException("Unable to obtain file name!");
    }

    // create "AoMeasurement" instance

    ODSInsertStatement ins = new ODSInsertStatement(modelCache, "mea");

    String mrName = null;
    if (useFileNameAsResultName)
    {
      mrName = FileUtil.getResultName(fileName.toString(), resultSuffix);
    }
    else
    {
      mrName = resultName + resultSuffix;
    }
    ins.setStringVal("iname", mrName);
    LOG.debug("MeaResult name: " + mrName);
    ins.setStringVal("mt", resultMimeType);

    if (addMDF3FileAsResultAttachment)
    {
      ins.setExtRefVal("attachment", new T_ExternalReference("original MDF-File", "", fileName.toString()));
    }

    // meta information
    HDBLOCK hdBlock = idBlock.getHDBlock();
    BLOCK block = hdBlock.getMdCommentBlock();
    if (block instanceof TXBLOCK)
    {
      ins.setStringVal("desc", ((TXBLOCK) block).getTxData());
    }
    else if (block instanceof MDBLOCK)
    {
      xmlParser.writeHDCommentToMea(ins, ((MDBLOCK) block).getMdData());
    }

    Calendar cal = Calendar.getInstance();
    cal.setTimeInMillis(hdBlock.getStartTimeNs() / 1000000);
    if (!hdBlock.isLocalTime() && hdBlock.isTimeFlagsValid())
    { // UTC time
      // given,
      // calc
      // local
      cal.add(Calendar.MINUTE, hdBlock.getTzOffsetMin());
      cal.add(Calendar.MINUTE, hdBlock.getDstOffsetMin());
    }
    ins.setDateVal("date_created", ODSHelper.asODSDate(cal.getTime()));
    ins.setDateVal("mea_begin", ODSHelper.asODSDate(cal.getTime()));
    ins.setLongLongVal("start_time_ns", hdBlock.getStartTimeNs());

    ins.setShortVal("local_time", hdBlock.isLocalTime() ? (short) 1 : (short) 0);
    ins.setShortVal("time_offsets_valid", hdBlock.isTimeFlagsValid() ? (short) 1 : (short) 0);
    ins.setShortVal("tz_offset_min", hdBlock.getTzOffsetMin());
    ins.setShortVal("dst_offset_min", hdBlock.getDstOffsetMin());

    ins.setEnumVal("time_quality_class", hdBlock.getTimeClass());
    ins.setShortVal("start_angle_valid", hdBlock.isStartAngleValid() ? (short) 1 : (short) 0);
    ins.setShortVal("start_distance_valid", hdBlock.isStartDistanceValid() ? (short) 1 : (short) 0);

    ins.setDoubleVal("start_angle_rad", hdBlock.getStartAngleRad());
    ins.setDoubleVal("start_distance_m", hdBlock.getStartDistanceM());

    // write attachments (ATBLOCK)
    if (!ignoreATBLOCKs && hdBlock.getLnkAtFirst() > 0)
    {
      Path root = idBlock.getMdfFilePath().getParent();
      String name = idBlock.getMdfFilePath().getFileName().toString().replaceAll("\\.[^.]+", "");
      T_ExternalReference[] extRefs = hdBlock.getAtFirstBlock().toExtRefs(root, copyToSub ? name : "");
      if (attachLinks2Tsts)
      {
        NameValueUnit nvu = ODSHelper.createExtRefSeqNVU("attachments", extRefs);
        modelCache.getApplicationElement("tst").getInstanceById(ODSHelper.asODSLongLong(iidTst)).setValue(nvu);
      }
      else
      {
        ins.setExtRefSeq("attachments", extRefs);
      }
    }

    // set Relations, to test
    ins.setLongLongVal("tst", iidTst);

    long iidMea = ins.execute();

    // write file history (FHBLOCK)
    Long[] iidFh = writeFh(modelCache, iidTst, hdBlock);

    // write channel hierarchy (CHBLOCK): not yet supported!
    if (hdBlock.getLnkChFirst() > 0)
    {
      LOG.warn("Found CHBLOCK, currently not yet supported!");
    }

    if (!readOnlyHeader)
    {
      writeEv(modelCache, iidTst, iidFh, hdBlock);

      // write submatrices
      Map<String, Integer> meqNames = new HashMap<>();
      writeSm(modelCache, iidMea, idBlock, hdBlock, meqNames);
    }
  }

  /**
   * Writes the content of all FHBLOCKS (file history) to the session.
   *
   * @param modelCache
   *        The application model cache.
   * @param ieTst
   *        The parent 'AoTest' instance.
   * @param hdBlock
   *        The HDBLOCK.
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  private Long[] writeFh(ODSModelCache modelCache, long iidTst, HDBLOCK hdBlock) throws AoException, IOException
  {
    int no = 1;
    FHBLOCK fhBlock = hdBlock.getFhFirstBlock();
    List<Long> iids = new LinkedList<Long>();
    while (fhBlock != null)
    {

      ODSInsertStatement ins = new ODSInsertStatement(modelCache, "fh");
      ins.setStringVal("iname", "fh_" + countFormat.format(no));

      // meta information
      Calendar cal = Calendar.getInstance();
      cal.setTimeInMillis(fhBlock.getStartTimeNs() / 1000000);
      if (!fhBlock.isLocalTime() && fhBlock.isTimeFlagsValid())
      { // UTC
        // time
        // given,
        // calc
        // local
        cal.add(Calendar.MINUTE, fhBlock.getTzOffsetMin());
        cal.add(Calendar.MINUTE, fhBlock.getDstOffsetMin());
      }

      ins.setNameValueUnit(ODSHelper.createDateNVU("date", ODSHelper.asODSDate(cal.getTime())));
      ins.setLongLongVal("start_time_ns", fhBlock.getStartTimeNs());
      ins.setShortVal("local_time", fhBlock.isLocalTime() ? (short) 1 : (short) 0);
      ins.setShortVal("time_offsets_valid", fhBlock.isTimeFlagsValid() ? (short) 1 : (short) 0);
      ins.setShortVal("tz_offset_min", fhBlock.getTzOffsetMin());
      ins.setShortVal("dst_offset_min", fhBlock.getDstOffsetMin());
      if (fhBlock.getLnkMdComment() != 0)
      {
        xmlParser.writeFHCommentToFh(ins, fhBlock.getMdCommentBlock().getMdData());
      }

      // set Relations.
      ins.setLongLongVal("tst", iidTst);
      iids.add(ins.execute());
      no++;
      fhBlock = fhBlock.getFhNextBlock();
    }
    return iids.toArray(new Long[0]);
  }

  /**
   * Writes the content of all EVBLOCKS (event) to the session.
   *
   * @param modelCache
   *        The application model cache.
   * @param ieTst
   *        The parent 'AoTest' instance.
   * @param hdBlock
   *        The HDBLOCK.
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  private void writeEv(ODSModelCache modelCache, long iidTst, Long[] iidFh, HDBLOCK hdBlock)
      throws AoException, IOException
  {
    int no = 1;
    EVBLOCK evBlock = hdBlock.getEvFirstBlock();
    while (evBlock != null)
    {
      if (evBlock.getLnkEvParent() != 0)
      {
        LOG.warn("Event Hirachy not supported.");
      }

      if (evBlock.getLnkEvRange() != 0)
      {
        LOG.warn("Event Range not supported.");
      }
      ODSInsertStatement ins = new ODSInsertStatement(modelCache, "ev");
      TXBLOCK name;
      if ((name = evBlock.getEvTxNameBlock()) != null)
      {
        ins.setStringVal("iname", name.getTxData());
      }
      else
      {
        ins.setStringVal("iname", "ev_" + countFormat.format(no));
      }

      // Get Descpription from XMLComment block
      BLOCK mdblock = evBlock.getMdCommentBlock();
      if (mdblock != null)
      {
        if (mdblock instanceof MDBLOCK)
        {
          xmlParser.writeEVCommentToEv(ins, ((MDBLOCK) mdblock).getMdData());
        }
        else if (mdblock instanceof TXBLOCK)
        {
          ins.setStringVal("desc", ((TXBLOCK) mdblock).getTxData());
        }
      }

      ins.setEnumVal("type", evBlock.getType());

      // System.out.println("Synctype: "+evBlock.getSyncType());

      ins.setEnumVal("sync_type", evBlock.getSyncType());
      ins.setEnumVal("range_type", evBlock.getRangeType());
      ins.setEnumVal("cause", evBlock.getCause());
      ins.setShortVal("flags", evBlock.getFlags());
      ins.setDoubleVal("sync_val", evBlock.getSyncValue());

      // set Relations.
      ins.setLongLongVal("tst", iidTst);
      if (evBlock.getCreatorIndex() < iidFh.length && evBlock.getCreatorIndex() >= 0)
      {
        ins.setLongLongVal("creator", iidFh[evBlock.getCreatorIndex()]);
      }

      ins.execute();

      no++;
      evBlock = evBlock.getEvNextBlock();
    }
  }

  /**
   * Write the instances of 'AoSubMatrix'.
   *
   * @param modelCache
   *        The application model cache.
   * @param iidMea
   *        The ID of the Parent Measurement.
   * @param idBlock
   *        The IDBLOCK.
   * @param hdBlock
   *        The HDBLOCK.
   * @param meqNames
   *        Map with existing MeasurmentQuantities and their IDs.
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  public void writeSm(ODSModelCache modelCache, long iidMea, IDBLOCK idBlock, HDBLOCK hdBlock,
      Map<String, Integer> meqNames) throws AoException, IOException
  {
    Map<String, Long> meqInstances = new HashMap<String, Long>();
    Map<String, Long> untInstances = new HashMap<String, Long>();
    // iterate over data group blocks
    int grpNo = 1;
    DGBLOCK dgBlock = hdBlock.getDgFirstBlock();
    while (dgBlock != null)
    {

      // if sorted, only one channel group block is available
      CGBLOCK cgBlock = dgBlock.getCgFirstBlock();

      if (cgBlock != null && cgBlock.getLnkCgNext() > 0)
      {
        throw new IOException(
            "Only 'sorted' MDF4 files are supported, found 'unsorted' data! [DGBLOCK=" + dgBlock + "]");
      }

      // skip channel groups having no channels (or optionally no values)
      boolean skipNoValues = skipEmptyChannels && cgBlock.getCycleCount() < 1;
      if (cgBlock != null && !skipNoValues)
      {

        // check flags (not yet supported)
        if (cgBlock.isBusEventChannel())
        {
          throw new IOException("Bus event data currently not supported! [DGBLOCK=" + dgBlock + "]");
        }

        // create SubMatrix instance
        ODSInsertStatement ins = new ODSInsertStatement(modelCache, "sm");
        String smName = "sm_" + countFormat.format(grpNo);
        ins.setStringVal("iname", smName);

        LOG.debug("SubMatrix name: " + smName);

        // write CGComment
        BLOCK mdblock = cgBlock.getMdCommentBlock();
        if (mdblock != null)
        {
          if (mdblock instanceof MDBLOCK)
          {
            xmlParser.writeCGCommentToCg(ins, ((MDBLOCK) mdblock).getMdData());
          }
          else if (mdblock instanceof TXBLOCK)
          {
            ins.setStringVal("desc", ((TXBLOCK) mdblock).getTxData());
          }
        }

        // write DGComment
        mdblock = dgBlock.getMdCommentBlock();
        if (mdblock != null)
        {
          if (mdblock instanceof MDBLOCK)
          {
            xmlParser.writeDGCommentToCg(ins, ((MDBLOCK) mdblock).getMdData());
          }
          else if (mdblock instanceof TXBLOCK)
          {
            ins.setStringVal("dg_desc", ((TXBLOCK) mdblock).getTxData());
          }
        }

        TXBLOCK txAcqName = cgBlock.getTxAcqNameBlock();
        if (txAcqName != null)
        {
          ins.setStringVal("acq_name", txAcqName.getTxData());
        }
        SIBLOCK siAcqSource = cgBlock.getSiAcqSourceBlock();
        if (siAcqSource != null)
        {
          writeSiBlock(ins, siAcqSource);
        }

        ins.setLongVal("rows", (int) cgBlock.getCycleCount());
        // Relation to measurement
        ins.setLongLongVal("mea", iidMea);
        long iidSm = ins.execute();

        ApplicationElement aeMea = modelCache.getApplicationElement("mea");
        InstanceElement ieMea = aeMea.getInstanceById(ODSHelper.asODSLongLong(iidMea));

        // write instances of
        // AoMeasurementQuantity,AoLocalColumn,AoExternalReference
        Map<String, Integer> mapMeq = new HashMap<String, Integer>();

        SRBLOCK srBlock = cgBlock.getSrFirstBlock();
        writeLc(modelCache, ieMea, iidSm, idBlock, dgBlock, cgBlock, srBlock, mapMeq, meqInstances, untInstances);
      }

      dgBlock = dgBlock.getDgNextBlock();
      grpNo++;
    }
  }

  /**
   * Write the instances of 'AoLocalColumn' and 'AoMeasurementQuantity'.
   *
   * @param modelCache
   *        The application model cache.
   * @param ieMea
   *        The parent 'AoMeasurement' instance.
   * @param iidSm
   *        The parent 'AoSubMatrix' instance id.
   * @param idBlock
   *        The IDBLOCK.
   * @param dgBlock
   *        The DGBLOCK.
   * @param cgBlock
   *        The CGBLOCK.
   * @param srBlock
   *        Possible SRBLOCK (can be null)
   * @param meqNames
   *        The so far cached 'AoMeasurementQuantity' names to the number of
   *        their occurrence, used for suffixing names with respective running
   *        number.
   * @param meqInstances
   *        The so far cached 'AoMeasurementQuantity' names to their iids.
   * @param untInstances
   *        The cached unit names to their iid, used in measurement quantity creation.
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  private void writeLc(ODSModelCache modelCache, InstanceElement ieMea, long iidSm, IDBLOCK idBlock, DGBLOCK dgBlock,
      CGBLOCK cgBlock, SRBLOCK srBlock, Map<String, Integer> meqNames, Map<String, Long> meqInstances,
      Map<String, Long> untInstances) throws AoException, IOException
  {
    // Performance?
    ApplicationElement aeLc = modelCache.getApplicationElement("lc");
    ApplicationElement aeSm = modelCache.getApplicationElement("sm");
    ApplicationRelation relLcSmLookup = modelCache.getApplicationRelation("lc", "sm", "LookupTable");
    ApplicationRelation relLcSmPrev = modelCache.getApplicationRelation("lc", "sm", "Previews");

    // iterate over channel blocks
    CNBLOCK cnBlock = cgBlock.getCnFirstBlock();
    List<String> channelNamesToSkip = getChannelNamesToSkip(cnBlock);
    long iidMea = ODSHelper.asJLong(ieMea.getId());
    while (cnBlock != null)
    {
      // build signal name
      String meqName = readMeqName(cnBlock).trim();
      // skip channel if configured
      if (channelNamesToSkip.contains(meqName))
      {
        LOG.debug("Skipping channel " + meqName);
        cnBlock = cnBlock.getCnNextBlock();
        continue;
      }
      
      LOG.debug("CNBLOCK=" + cnBlock);
      
      if ((cnBlock.getFlags() & 0x02) != 0 && cnBlock.getInvalBitPos() > 0)
      {
        if (writeFlagsFile)
        {
          // NOTE: flags are exported within writeEc()!
          LOG.debug(
              "channel with invalid values found, " + "export flags into separate file [CNBLOCK=" + cnBlock + "]");
        }
        else
        {
          LOG.debug("skipping channel with invalid values [CNBLOCK=" + cnBlock + "]");
          continue;
        }
      }

      // TODO cn_at_reference: attachments
      if (cnBlock.getLnkAtReference().length > 0)
      {
        LOG.warn("Found channel 'cn_at_reference'>0, not yet supported ");
      }

      // replace channel names (concerto invalid characters)
      if (replaceSquareBrackets)
      {
        meqName = meqName.replaceAll("\\[", "{");
        meqName = meqName.replaceAll("\\]", "}");
      }

      LOG.debug("Channel name: " + meqName);

      // check for duplicate signal names and add suffix (except time
      // channel)
      if (cnBlock.getChannelType() == 0)
      {
        Integer noChannels = meqNames.get(meqName);
        if (noChannels == null)
        {
          noChannels = 0;
        }
        noChannels++;
        meqNames.put(meqName, noChannels);
        if (noChannels > 1)
        {
          meqName = meqName + "_" + noChannels;
        }
      }

      CCBLOCK ccBlock = cnBlock.getCcConversionBlock();

      // check whether channel has to be or shall be skipped
      if (skipScaleConversionChannels && ccBlock != null && ccBlock.hasCCRefs())
      {
        LOG.info("Channel '" + meqName + "' with scale conversion rules in CCBlocks skipped: " + ccBlock);
        cnBlock = cnBlock.getCnNextBlock();
        continue;
      }
      else if (skipByteStreamChannels && 10 == cnBlock.getDataType())
      {
        // remove this block once it is save to import channels with
        // byte stream data
        LOG.info("Channel '" + meqName + "' with byte stream data skipped: " + ccBlock);
        cnBlock = cnBlock.getCnNextBlock();
        continue;
      }
      else if (10 == cnBlock.getDataType() && cnBlock.getLnkComposition() != 0)
      {
        LOG.info("Channel '" + meqName + "' with composed byte stream data skipped: " + ccBlock);
        cnBlock = cnBlock.getCnNextBlock();
        continue;
      }
      else if (64 == cnBlock.getBitCount()
          && (0 /* LEO */ == cnBlock.getDataType() || 1 /* BEO */ == cnBlock.getDataType()))
      {
        // UNSIGNED 64 bit: if cnBlock represents a time channel (sync_type ==
        // 1)
        // => it is considered save to interpret data as signed 64 bit
        // => otherwise either fail or skip
        if (1 != cnBlock.getSyncType())
        {
          // this is a data channel with 64 bit unsigned data; it is not
          // possible to represent such data
          // => either throw an error or skip channel
          if (skipUINT64Channels)
          {
            LOG.info("Channel '" + meqName + "' with unsigned 64 bit data skipped: " + cnBlock);
            cnBlock = cnBlock.getCnNextBlock();
            continue;
          }
          else
          {
            throw new IOException("unable to write unsigned 64 bit data channel");
          }
        }
      }

      BLOCK compositionBlock = null;
      if (cnBlock.getLnkComposition() != 0)
      {
        LOG.debug("Composition found!");
        compositionBlock = cnBlock.getCompositionBlock();
      }

      // create instance of 'AoMeasurementQuantity' (if not yet existing)
      Long iidMeq = meqInstances.get(meqName);
      if (iidMeq == null)
      {
        iidMeq = createMeasurementQuantity(modelCache, cnBlock, ccBlock, compositionBlock, meqName, iidMea, null,
            untInstances);
        meqInstances.put(meqName, iidMeq);
      }

      // create 'AoLocalColumn' instance
      long iidLc = createLocalColumn(modelCache, dgBlock, cgBlock, cnBlock, ccBlock, compositionBlock, meqName, iidMea,
          iidSm, iidMeq, null);
      
      // create previews
      if (!skipPreviews && srBlock != null && (cnBlock.getChannelType() < 2 || cnBlock.getChannelType() > 4))
      {
        // previews should only be created for the data channels, not for any
        // master or synchronization channel, therefore only link and create 
        // those previews
        InstanceElement ieLc = aeLc.getInstanceById(ODSHelper.asODSLongLong(iidLc));
        previewHelper.createPreviewChannels(ieMea, ieLc, meqName, srBlock, idBlock, cgBlock,
            dgBlock, cnBlock, ccBlock, untInstances, relLcSmPrev);
      }
      
      // create 'AoExternalComponent' instance (if not a string data type
      // (6-9) or VLSD-Channel (Type ==1) or virtual master channel (Type == 3))
      Boolean setGlobalFlag = null;
      if (!(cnBlock.getDataType() >= 6 && cnBlock.getDataType() <= 9 || cnBlock.getChannelType() == 1
          || cnBlock.getChannelType() == 3))
      {
        setGlobalFlag = writeEc(modelCache, iidLc, idBlock, dgBlock, cgBlock, cnBlock, ccBlock, compositionBlock,
            dgBlock.getLnkData(), 0);
      }

      // set the global flag to the channel if returned by writeEc
      if (setGlobalFlag != null)
      {
        InstanceElement ieLc = aeLc.getInstanceById(ODSHelper.asODSLongLong(iidLc));
        TS_Union union = new TS_Union();
        union.shortVal(Boolean.TRUE.equals(setGlobalFlag) ? (short) 15 : 0);
        ieLc.setValue(new NameValueUnit("glb", new TS_Value(union, (short) 15), ""));
      }

      // create Table for Lookup conversion, if conversion type is 4 to 10
      InstanceElement ieLc = aeLc.getInstanceById(ODSHelper.asODSLongLong(iidLc));

      if (ccBlock != null && ccBlock.getType() >= 4 && ccBlock.getType() <= 10)
      {
        long iidLookup = createLookupTable(modelCache, ccBlock, ieMea, ieLc);
        InstanceElement ieSmLookup = aeSm.getInstanceById(ODSHelper.asODSLongLong(iidLookup));
        ieLc.createRelation(relLcSmLookup, ieSmLookup);
      }

      // jump to next channel
      cnBlock = cnBlock.getCnNextBlock();
    }
  }
  
  /**
   * If configured, remove the .texttable and .linear channels which may
   * have been added by a special feature of ETAS' INCA application.
   * Otherwise those conversions are redundantly created and multiplied.
   * 
   * @param name
   * @return
   * @throws IOException 
   */
  private List<String> getChannelNamesToSkip(CNBLOCK firstCnBlock) throws IOException
  {
    List<String> channelNames = new ArrayList<>();
    if (!skipExtraConversionChannels)
    {
      return channelNames;
    }
    
    CNBLOCK cnBlock = firstCnBlock;
    while (cnBlock != null)
    {
      channelNames.add(readMeqName(cnBlock));
      cnBlock = cnBlock.getCnNextBlock();
    }
    
    List<String> namesToSkip = new ArrayList<>();
    for (String currentName : channelNames)
    {
      String originalChannelName = null;
      if (currentName.endsWith(ENDING_TEXTTABLE))
      {
        int index = currentName.indexOf(ENDING_TEXTTABLE);
        originalChannelName = currentName.substring(0, index);
      }
      else if (currentName.endsWith(ENDING_LINEAR))
      {
        int index = currentName.indexOf(ENDING_LINEAR);
        originalChannelName = currentName.substring(0, index);
      }
      
      if (originalChannelName != null && !originalChannelName.isEmpty() && channelNames.contains(originalChannelName))
      {
        namesToSkip.add(currentName);
      }
    }
    
    return namesToSkip;
  }

  /**
   * Create and insert the actual MeasurementQuantity This function also creates
   * the corresponding unit if it doesn't already exist.
   * 
   * @param modelCache
   *        Cache with model Object
   * @param cnBlock
   *        The Channel Block.
   * @param ccBlock
   *        The Conversion Block.
   * @param compositionBlock
   *        The composition Block, may be null.
   * @param meqName
   *        The Name the Measurement will have.
   * @param iidMea
   *        The ID of the Measurement this Quantity is related to.
   * @param mimeType
   *        The MIME-Type of this MeasurementQuantity. if mimeType==null, no
   *        MIME-Type is set.
   * @param untInstances
   *        Map that contains iids of all created units so far. Key is the name
   *        of the unit
   * @return The ID of the created MeasurmentQuantity
   * @throws IOException
   *         If an I/O-error occurs.
   * @throws AoException
   */
  long createMeasurementQuantity(ODSModelCache modelCache, CNBLOCK cnBlock, CCBLOCK ccBlock, BLOCK compositionBlock,
      String meqName, long iidMea, String mimeType, Map<String, Long> untInstances) throws IOException, AoException
  {
    int seqRep = getSeqRep(cnBlock, ccBlock);
    double[] genParams = getGenerationParameters(ccBlock);

    ODSInsertStatement ins = new ODSInsertStatement(modelCache, "meq");
    ins.setStringVal("iname", meqName);

    // Write XML MetaData
    BLOCK mdblock = cnBlock.getMdCommentBlock();
    if (mdblock instanceof MDBLOCK)
    {
      xmlParser.writeCNCommentToMeq(ins, ((MDBLOCK) mdblock).getMdData());
    }
    else if (mdblock instanceof TXBLOCK)
    {
      ins.setStringVal("desc", ((TXBLOCK) mdblock).getTxData().trim());
    }

    // MIME-Type
    if (mimeType != null)
    {
      ins.setStringVal("mt", mimeType);
    }

    boolean expandDataType = genParams != null && genParams.length > 0 && seqRep != 0 && seqRep != 7;
    ins.setEnumVal("dt", getDataType(expandDataType, cnBlock, ccBlock));

    if (ccBlock != null && ccBlock.isPhysicalRangeValid())
    {
      ins.setDoubleVal("min", ccBlock.getPhyRangeMin());
      ins.setDoubleVal("max", ccBlock.getPhyRangeMax());
    }
    /*
     * // CEBLOCK (extension block) info CEBLOCK ceBlock = cnBlock.getCeblock();
     * if (ceBlock != null && ceBlock.getCeBlockDim() != null) { CEBLOCK_DIM ext
     * = ceBlock.getCeBlockDim(); ins.setLongVal("NumberOfModule",
     * ext.getNumberOfModule()); ins.setLongLongVal("Address",
     * ext.getAddress()); ins.setStringVal("DIMDescription",
     * ext.getDescription()); ins.setStringVal("ECUIdent", ext.getEcuIdent()); }
     * else if (ceBlock != null && ceBlock.getCeBlockVectorCAN() != null) {
     * CEBLOCK_VectorCAN ext = ceBlock.getCeBlockVectorCAN();
     * ins.setLongLongVal("CANIndex", ext.getCanIndex());
     * ins.setLongLongVal("MessageId", ext.getMessageId());
     * ins.setStringVal("MessageName", ext.getMessageName());
     * ins.setStringVal("SenderName", ext.getSenderName()); }
     */
    ins.setLongLongVal("mea", iidMea);

    SIBLOCK siBlock = cnBlock.getSiSourceBlock();
    if (siBlock != null)
    {
      writeSiBlock(ins, siBlock);
    }

    // create 'AoUnit' instance if not yet existing
    long uiid = writeUnit(modelCache, cnBlock, ccBlock, untInstances);
    if (uiid != -1)
    {
      ins.setLongLongVal("unt", uiid);
    }

    // handle composition block and transform into according MeaQuantity
    handleCompositionInfo(compositionBlock, ins);

    return ins.execute();
  }

  /**
   * Handles composition of blocks. Only array composition is supported so far.
   * 
   * @param compositionBlock
   *        The composition Block, may be null.
   * @param ins
   *        the insert statement for a MeaQuantity
   * @throws IOException
   */
  private void handleCompositionInfo(BLOCK compositionBlock, ODSInsertStatement ins) throws IOException
  {
    if (compositionBlock == null)
    {
      return;
    }

    CABLOCK arrayCompositionBlock = null;
    if (compositionBlock instanceof CNBLOCK)
    {
      throw new IOException("Channel Composition based on compact structures not yet supported!");
    }
    else if (compositionBlock instanceof CABLOCK)
    {
      LOG.debug("Array block for composition: [" + compositionBlock + "]");
      arrayCompositionBlock = (CABLOCK) compositionBlock;
    }

    if (arrayCompositionBlock != null)
    {
      handleArrayComposition(arrayCompositionBlock, ins);
    }
  }

  /**
   * Handles array compositions. The ods information on rank and dimension is
   * read from the CABLOCK. Additionally the inverse layout flag has to be
   * transferred as well, otherwise no client may correctly calculate the values
   * from the tensor in this channel. This additional flag is not yet specified
   * by ODS, but will be written as an application attribute 'columnOriented' to
   * the MeaQuantity.
   * 
   * @param arrayCompositionBlock
   * @param ins
   *        the insert statement for a MeaQuantity
   * @throws IOException
   */
  private void handleArrayComposition(CABLOCK arrayCompositionBlock, ODSInsertStatement ins) throws IOException
  {
    if (arrayCompositionBlock == null || ins == null)
    {
      return;
    }

    // set the rank attribute of the MeaQuantity
    int odsRank = arrayCompositionBlock.getNrOfDimensions();
    ins.setLongVal(ODSModelCache.ATTR_NAME_MEAQU_RANK, odsRank);

    // set the dimension attribute of the MeaQuantity
    long[] longDimSizes = arrayCompositionBlock.getDimSizes();
    int[] odsDimension = new int[longDimSizes.length];
    for (int i = 0; i < longDimSizes.length; i++)
    {
      long currentDimSize = longDimSizes[i];
      if (currentDimSize > Integer.MAX_VALUE)
      {
        throw new IOException("Found dimension (index=" + i + ") in MDF with more values (" + currentDimSize
            + ") than can be handled by ODS!");
      }
      odsDimension[i] = (int) currentDimSize;
    }
    ins.setLongSeq(ODSModelCache.ATTR_NAME_MEAQU_DIMENSION, odsDimension);

    // set the ColumnOriented attribute of the MeaQuantity
    boolean odsInverseLayout = arrayCompositionBlock.isFlagSet(CABLOCK.FLAG_INVERSE_LAYOUT);
    ins.setBooleanVal(ODSModelCache.ATTR_NAME_MEAQU_COL_ORIENTED_TENSOR, odsInverseLayout);

    // TODO handle working points

    // handle scaling axes
    if (arrayCompositionBlock.isFlagSet(CABLOCK.FLAG_SCALING_AXIS_DEFINED))
    {
      if (arrayCompositionBlock.isFlagSet(CABLOCK.FLAG_FIXED_AXES))
      {
        // throw new IOException("Handling of fixed scaling axes for arrays is
        // not yet implemented!");
      }
      else
      {
        // throw new IOException("Handling of variable scaling axes for arrays
        // is not yet implemented!");
      }
    }
  }

  /**
   * Create and insert the actual LocalColumn.
   * 
   * @param modelCache
   *        Cache with model Object
   * @param dgBlock
   *        The Data Group Block.
   * @param cgBlock
   *        The Channel Group Block.
   * @param cnBlock
   *        The Channel Block.
   * @param ccBlock
   *        The Conversion Block.
   * @param compositionBlock
   *        The composition Block.
   * @param lcName
   *        The Name the Local Column will have.
   * @param iidMea
   *        The ID of the Measurement this LocalColumn's SubMatrix will be
   *        related to in case of array composition.
   * @param iidSm
   *        The ID of the SubMatrix this LocalColumn is related to.
   * @param iidMeq
   *        The ID of the MeasurementQuantity this LocalColumn is related to.
   * @param mimeType
   *        The MIME-Type of this MeasurementQuantity. if mimeType==null, no
   *        MIME-Type is set.
   * @return The ID of the created MeasurmentQuantity
   * @throws IOException
   *         If an I/O-error occurs.
   * @throws AoException
   */
  long createLocalColumn(ODSModelCache modelCache, DGBLOCK dgBlock, CGBLOCK cgBlock, CNBLOCK cnBlock, CCBLOCK ccBlock,
      BLOCK compositionBlock, String lcName, long iidMea, long iidSm, long iidMeq, String mimeType)
      throws IOException, AoException
  {
    int seqRep = getSeqRep(cnBlock, ccBlock);
    double[] genParams = getGenerationParameters(ccBlock);
    ODSInsertStatement ins = new ODSInsertStatement(modelCache, "lc");
    ins.setStringVal("iname", lcName);

    // MIME-Type
    if (mimeType != null)
    {
      ins.setStringVal("mt", mimeType);
    }
    // global flag
    ins.setShortVal("glb", (short) 15);

    // sequence_representation: string channels cannot be referenced in ASAM
    // ODS: read and write external
    if (cnBlock.getDataType() >= 6 && cnBlock.getDataType() <= 9 && cnBlock.getChannelType() != 1)
    { // 6 To 9:
      // Datatype
      // String
      String[] stringDataValues = readStringDataValues(dgBlock, cgBlock, cnBlock);
      ins.setEnumVal("srp", 0);
      ins.setNameValueUnit(ODSHelper.createStringSeqNVU("val", stringDataValues));
      LOG.info("Unable to reference into MDF4, extracting string values. [Channel=" + lcName + "]");
    }
    else if (cnBlock.getChannelType() == 1)
    {
      // Read VLSDChannel values.
      ins.setEnumVal("srp", 0);
      LOG.info("Variable Length Channel! [Channel=" + lcName + "]");
      insertVLSDValues(ins, dgBlock, cgBlock, cnBlock);
    }
    else
    {
      ins.setEnumVal("srp", seqRep);
    }

    // independent flag
    short idp = cnBlock.getSyncType() > 0 ? (short) 1 : (short) 0;
    ins.setShortVal("idp", idp);

    // generation parameters
    ins.setDoubleSeq("par", genParams);

    // raw_datatype
    int valueType = getValueType(cnBlock);
    int rawDataType = getRawDataTypeForValueType(valueType, cnBlock);
    ins.setEnumVal("rdt", rawDataType);

    // axistype
    int axistype = cnBlock.getSyncType() == 0 ? 1 : 0;
    ins.setEnumVal("axistype", axistype);
    // minimum/maximum
    if (cnBlock.isValueRangeValid())
    {
      ins.setDoubleVal("min", cnBlock.getValRangeMin());
      ins.setDoubleVal("max", cnBlock.getValRangeMax());
    }

    // identify the actual SubMatrix to connect to
    long actualSubMatrixId = identifySubMatrixIdToConnect(modelCache, cgBlock, compositionBlock, iidSm, iidMea);

    // relation to submatrix
    ins.setLongLongVal("sm", actualSubMatrixId);
    ins.setLongLongVal("meq", iidMeq);

    long iidLc = ins.execute();
    return iidLc;
  }

  /**
   * For array composition, the nrOfValues for the SubMatrix has to be
   * corrected. An according array channel will have the following length:
   * cycleCount * dimSize1 * ... * dimSizeN Therefore a new SubMatrix with this
   * nrOfRows may have to be created. If one with this length was already
   * created, its ID is returned. If no composition was passed, the original
   * SubMatrix ID is returned.
   * 
   * @param modelCache
   *        Cache with model Objects.
   * @param cgBlock
   *        The CGBLOCK.
   * @param compositionBlock
   *        The composition Block.
   * @param originalSmId
   *        If compositionBlock is null, this ID will be returned.
   * @param iidMea
   *        The measurement ID to connect a newly created SubMatrix to.
   * @return SubMatrix ID to be used for the LocalColumn, for which this method
   *         was called.
   * @throws AoException
   */
  private long identifySubMatrixIdToConnect(ODSModelCache modelCache, CGBLOCK cgBlock, BLOCK compositionBlock,
      long originalSmId, long iidMea) throws AoException
  {
    long actualSubMatrixId = originalSmId;
    if (compositionBlock instanceof CABLOCK && iidMea > 0)
    {
      long smNrOfValues = cgBlock.getCycleCount();
      long[] dimSizes = ((CABLOCK) compositionBlock).getDimSizes();
      for (long dimSize : dimSizes)
      {
        smNrOfValues *= dimSize;
      }

      Long existingArraySubmatrixId = arraySubMatrixIDsByNrOfValues.get(smNrOfValues);

      if (existingArraySubmatrixId == null)
      {
        // create array SubMatrix instance
        ODSInsertStatement smIns = new ODSInsertStatement(modelCache, "sm");
        String smName = "sm_arrays_" + smNrOfValues;
        smIns.setStringVal("iname", smName);

        LOG.debug("SubMatrix name: " + smName);

        smIns.setLongVal("rows", (int) smNrOfValues);
        // Relation to measurement
        smIns.setLongLongVal("mea", iidMea);
        actualSubMatrixId = smIns.execute();
        arraySubMatrixIDsByNrOfValues.put(smNrOfValues, actualSubMatrixId);
      }
      else
      {
        actualSubMatrixId = existingArraySubmatrixId;
      }
    }
    return actualSubMatrixId;
  }

  /**
   * Read values from an VLSD-Channel and write them directly to file.
   *
   * @param ins
   *        The Insertstatement to use.
   * @param cnBlock
   *        The VLSD-Channel
   * @throws IOException
   */
  private void insertVLSDValues(ODSInsertStatement ins, DGBLOCK dgBlock, CGBLOCK cgBlock, CNBLOCK cnBlock)
      throws IOException
  {
    BLOCK blk = cnBlock.getDataBlock();
    if (blk == null)
    {
      // assume empty SDBLOCK
      ins.setNameValueUnit(ODSHelper.createStringSeqNVU("val", new String[0]));
      return;
    }
    else if (!(blk instanceof SDBLOCK))
    {
      throw new RuntimeException("Found VLSD Block with no valid signal data.");
    }
    SDBLOCK sdBlock = (SDBLOCK) blk;

    // start Reading the values.
    SeekableByteChannel sbc = cnBlock.sbc;
    long recordSize = dgBlock.getRecIdSize() + cgBlock.getDataBytes() + cgBlock.getInvalBytes();
    long recStart = dgBlock.getLnkData() + 24L;
    long[] offsets = new long[(int) cgBlock.getCycleCount()];

    long valueBitSize = cnBlock.getBitCount() + cnBlock.getBitOffset();
    int valueByteSize = (int) (valueBitSize % 8 == 0 ? valueBitSize / 8 : valueBitSize / 8 + 1);
    long offset = cnBlock.getByteOffset();
    ByteBuffer bb = ByteBuffer.allocate(valueByteSize);

    // iterate over records and read offsets
    long pos = recStart;
    for (int i = 0; i < cgBlock.getCycleCount(); i++)
    {
      // read offset
      bb.rewind();
      sbc.position(pos + offset);
      sbc.read(bb);
      bb.rewind();
      offsets[i] = MDF4Util.readValue(cnBlock.getBitOffset(), (int) cnBlock.getBitCount(), bb);
      pos += recordSize;
    }

    // read data
    // iterate over records
    ByteBuffer signals = ByteBuffer.allocate((int) (sdBlock.getLength() - 24));

    long signalpos = cnBlock.getLnkData() + 24L;
    sbc.position(signalpos);

    sbc.read(signals);
    signals.rewind();

    LinkedList<String> list = new LinkedList<String>();
    for (int i = 0; i < cgBlock.getCycleCount(); i++)
    {
      signals.position((int) offsets[i]);
      int size = (int) MDF4Util.readUInt32(signals.order(ByteOrder.LITTLE_ENDIAN));
      // read record
      byte[] record = new byte[size];
      signals.get(record);

      // build string value and append to list.
      // Switch for different encodings.
      String value;
      switch (cnBlock.getDataType())
      {
      case 6: // ISO-8859
        value = MDF4Util.readCharsISO8859(ByteBuffer.wrap(record), record.length);
        break;
      case 7: // UTF-8
        value = MDF4Util.readCharsUTF8(ByteBuffer.wrap(record), record.length);
        break;
      case 8: // UFT-16LE
        value = MDF4Util.readCharsUTF16(ByteBuffer.wrap(record), record.length, true);
        break;
      case 9: // UTF-16BE
        value = MDF4Util.readCharsUTF16(ByteBuffer.wrap(record), record.length, false);
        break;
      default:
        throw new IllegalArgumentException("Illegal String encoding. Other encodings for VLSD not supported.");
      }
      list.add(value);
    }
    ins.setNameValueUnit(ODSHelper.createStringSeqNVU("val", list.toArray(new String[0])));
  }

  /**
   * Creates a Lookup-Table from the given conversion Block. (must not be null!)
   *
   * @param modelCache
   * @param cc
   * @return The iid of the SubMatrix
   * @throws IOException
   * @throws AoException
   */
  private long createLookupTable(ODSModelCache modelCache, CCBLOCK ccBlock, InstanceElement ieMea, InstanceElement ieLc)
      throws IOException, AoException
  {
    // Scale Lookups are not yet supported.
    if (ccBlock.getType() == 4 || ccBlock.getType() == 5)
    {
      double[] keys = ccBlock.getSecondValues(true);
      double[] values = ccBlock.getSecondValues(false);
      return lookupTableHelper.createValueToValueTable(modelCache, ieMea, ieLc, keys, values, ccBlock.getType() == 4);
    }
    else if (ccBlock.getType() == 6)
    {
      double[] minKeys = ccBlock.getThirdValues(0);
      double[] maxKeys = ccBlock.getThirdValues(1);
      double[] values = ccBlock.getThirdValues(2);
      return lookupTableHelper.createValueRangeToValueTable(modelCache, ieMea, ieLc, minKeys, maxKeys, values, ccBlock);
    }
    else if (ccBlock.getType() == 7)
    { // Value to Text/Scale lookup
      double[] keys = ccBlock.getValues();
      String[] values = ccBlock.getValuesForTextTable(ieLc.getName(), ignoreUnsupportedConversionTypes);
      if (values.length != keys.length)
      {
        LOG.warn("Number of values and keys for Lookup-Table are not equal!");
      }
      return lookupTableHelper.createValueToTextTable(modelCache, ieMea, ieLc, keys, values, ccBlock);
    }
    else if (ccBlock.getType() == 8)
    { // Value Range to Text/Scale lookup
      double[] keysMin = ccBlock.getSecondValues(true);
      double[] keysMax = ccBlock.getSecondValues(false);
      String[] values = ccBlock.getValuesForTextTable(ieLc.getName(), ignoreUnsupportedConversionTypes);
      return lookupTableHelper.createValueRangeToTextTable(modelCache, ieMea, ieLc, keysMin, keysMax, values, ccBlock);
    }
    else if (ccBlock.getType() == 9)
    {
      String[] keys = ccBlock.getRefValues(ieLc.getName(), ignoreUnsupportedConversionTypes);
      double[] values = ccBlock.getValuesForTextToValueTable();
      return lookupTableHelper.createTextToValueTable(modelCache, ieMea, ieLc, keys, values, ccBlock);
    }
    else if (ccBlock.getType() == 10)
    {
      String channelName = ieLc.getName();
      String[] keys = ccBlock.getSecondTexts(true, channelName, ignoreUnsupportedConversionTypes);
      String[] values = ccBlock.getSecondTexts(false, channelName, ignoreUnsupportedConversionTypes);
      return lookupTableHelper.createTextToTextTable(modelCache, ieMea, ieLc, keys, values, ccBlock);
    }
    else
    {
      LOG.warn("Unsupported Conversion.");
      return 0;
    }
  }

  /**
   * Reads String values from a string channel.
   * 
   * @param dgBlock
   *        The data group block.
   * @param cgBlock
   *        The channel group block.
   * @param cnBlock
   *        The channel block.
   * @return The values as String-Array.
   * @throws IOException
   *         If an input error occurs.
   */
  private static String[] readStringDataValues(DGBLOCK dgBlock, CGBLOCK cgBlock, CNBLOCK cnBlock) throws IOException
  {
    List<String> list = new ArrayList<>();

    SeekableByteChannel sbc = dgBlock.sbc;
    int recordIdOffset = dgBlock.getRecIdSize();
    long mapStart = dgBlock.getLnkData() + 24L;
    long mapSize = (cgBlock.getDataBytes() + recordIdOffset) * cgBlock.getCycleCount();
    
    // For huge string channels it is necessary to split the data block into
    // smaller partitions, because otherwise the mapSize would exceed the
    // Integer.MAX_VALUE size of the byte buffer allocation and cause an
    // Exception. A good enough compromise should be a cycle count of 200.000.
    // Also the buffer may exceed the VM's size if too big.
    long restSize = mapSize;
    int maxReadRecords = 200000; // cycle count of 200.000 allows up to around 10.7KB record size and yields a 100MB buffer in memory at record size 500B
    int maxValue = (int) (cgBlock.getDataBytes() + recordIdOffset) * maxReadRecords; 
    while (restSize > 0)
    {
      int currentMapSize = maxValue;
      int currentRecordCount = maxReadRecords;
      if (restSize < maxValue)
      {
        currentMapSize = (int) restSize;
        currentRecordCount = (int) (restSize / (cgBlock.getDataBytes() + recordIdOffset));
        restSize = 0; 
      }
      else
      {
        restSize -= maxValue;
      }
      
      ByteBuffer bb = ByteBuffer.allocate(currentMapSize);
      sbc.position(mapStart);
      sbc.read(bb);
      bb.rewind();
      mapStart += currentMapSize;
      
      // iterate over records
      for (int i = 0; i < currentRecordCount; i++)
      {
        // read record
        byte[] dataRecord = new byte[(int) (cgBlock.getDataBytes() + recordIdOffset)];
        bb.get(dataRecord);

        // skip first bits and read value
        BitInputStream bis = new BitInputStream(dataRecord);
        int skipBits = (int) (recordIdOffset * 8L + cnBlock.getByteOffset() * 8L + cnBlock.getBitOffset());
        bis.skip(skipBits);
        byte[] b = bis.readByteArray((int) cnBlock.getBitCount());

        // build string value and append to list.
        // Switch for different encodings.
        String value;
        switch (cnBlock.getDataType())
        {
        case 6: // ISO-8859
          value = MDF4Util.readCharsISO8859(ByteBuffer.wrap(b), b.length);
          break;
        case 7: // UTF-8
          value = MDF4Util.readCharsUTF8(ByteBuffer.wrap(b), b.length);
          break;
        case 8: // UFT-16LE
          value = MDF4Util.readCharsUTF16(ByteBuffer.wrap(b), b.length, true);
          break;
        case 9: // UTF-16BE
          value = MDF4Util.readCharsUTF16(ByteBuffer.wrap(b), b.length, false);
          break;
        default:
          throw new IllegalArgumentException("Illegal String encoding.");
        }
        list.add(value);
      }
    }

    return list.toArray(new String[0]);
  }

  /**
   * Write the instances of 'AoExternalComponent'. One instance is written for
   * each data block.
   *
   * @param modelCache
   *        The application model cache.
   * @param iidLc
   *        The instance id of the 'AoLocalColumn' instance.
   * @param idBlock
   *        The IDBLOCK.
   * @param dgBlock
   *        The DGBLOCK.
   * @param cgBlock
   *        The CGBLOCK.
   * @param cnBlock
   *        The CNBLOCK.
   * @param ccBlock
   *        The CCBLOCK.
   * @param compositionBlock
   *        The composition Block, may be null.
   * @param sectionstart
   *        The link to data, can be a DL, RD or DT Block or HL, DZ, but these
   *        are not supported.
   * @param parity
   *        Used for previews, where only each third record has to be addressed.
   *        If every record will be addressed, parity has to be set to 0.
   *        Otherwise valid values are 1, 2 and 3. (e.g. if parity==1 the first
   *        of each three records will be addressed)
   *
   * @return true, if the global flag of the channel has to be set to valid, false for invalid, null otherwise
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  Boolean writeEc(ODSModelCache modelCache, long iidLc, IDBLOCK idBlock, DGBLOCK dgBlock, CGBLOCK cgBlock,
      CNBLOCK cnBlock, CCBLOCK ccBlock, BLOCK compositionBlock, long sectionstart, int parity)
      throws AoException, IOException
  {
    Boolean setGlobalFlag = null;
    if (isRatConv2ExtComp(ccBlock))
    {
      // NOTE: once CCBLOCK is no longer required, it should be removed
      // from this method's signature!
      setGlobalFlag = createCustomRatConvEC(modelCache, iidLc, idBlock, dgBlock, cgBlock, cnBlock, ccBlock, sectionstart, parity);
    }
    else
    {
      DLBLOCK currdl = null; // current list block
      int dlindex = 0; // index in data list block.
      int totalindex = 0; // number of blocks read;
      long currblock = -1;

      switch (BLOCK.getBlockType(idBlock.sbc, sectionstart))
      {
      case "##DT":
      case "##RD":
        currblock = sectionstart;
        break;
      case "##DL":
        currdl = DLBLOCK.read(idBlock.sbc, sectionstart);
        currblock = currdl.getLnkDlData()[0];
        // perform check for records over blockborders.
        if (currdl.breaksRecords(cgBlock.getDataBytes() + dgBlock.getRecIdSize() + cgBlock.getInvalBytes()))
        {
          throw new IOException("This data list cannot be read because records are splitted.");
        }
        break;
      case "##DZ":
      case "##HL":
        throw new IOException("Zipped blocks cannot be parsed into the ODS-Format.");
      }

      ODSInsertStatement ins = new ODSInsertStatement(modelCache, "ec");
      while (currblock != -1)
      {
        ins.setStringVal("iname", "ec_" + countFormat.format(++totalindex));
        Path mdfFilePath = idBlock.getMdfFilePath().getFileName();
        if (mdfFilePath == null)
        {
          throw new IOException("mdfFilePath must not be null");
        }

        long startOffset = currblock + 24L;
        ins.setLongVal("on", totalindex);
        ins.setStringVal("fl", mdfFilePath.toString());

        int vt = getValueType(cnBlock);
        ins.setEnumVal("vt", vt);
        ins.setLongLongVal("so", startOffset);

        int valuesPerBlock = 1; // default is one value per block
        if (compositionBlock != null)
        {
          if (compositionBlock instanceof CABLOCK)
          {
            // for array composition set valuesPerBlock to the product of all
            // dim sizes
            long[] dimSizes = ((CABLOCK) compositionBlock).getDimSizes();
            for (long dimSize : dimSizes)
            {
              valuesPerBlock *= dimSize;
            }
          }
        }
        // TODO Strings, write number of Bytes? Spec4/61
        ins.setLongVal("vb", valuesPerBlock);

        // Calculate ByteSize and Offset
        long bytesize;
        long valueOffset;
        long recSizeWoInval = cgBlock.getDataBytes() + dgBlock.getRecIdSize();
        if (parity == 0)
        {
          bytesize = recSizeWoInval + cgBlock.getInvalBytes();
          valueOffset = dgBlock.getRecIdSize() + cnBlock.getByteOffset() + cnBlock.getBitOffset() / 8;
        }
        else
        {
          // inval bytes once at the end
          bytesize = 3 * recSizeWoInval + cgBlock.getInvalBytes();
          valueOffset = (parity - 1) * recSizeWoInval + dgBlock.getRecIdSize() + cnBlock.getByteOffset()
              + cnBlock.getBitOffset() / 8;
        }

        ins.setLongVal("bs", (int) bytesize);
        ins.setLongVal("vo", (int) valueOffset);

        // get Cycle count from Block size.
        int cycleCount = -1;
        if (BLOCK.getBlockType(idBlock.sbc, currblock).equals(DTBLOCK.BLOCK_ID))
        {
          cycleCount = (int) ((DTBLOCK.read(idBlock.sbc, currblock).getLength() - 24) / bytesize);
        }
        else if (BLOCK.getBlockType(idBlock.sbc, currblock).equals(RDBLOCK.BLOCK_ID))
        {
          cycleCount = (int) ((RDBLOCK.read(idBlock.sbc, currblock).getLength() - 24) / bytesize);
        }
        else
        {

        }

        // for array composition the component length must be adjusted like for
        // the SubMatrix nrOfRows
        if (compositionBlock != null)
        {
          if (compositionBlock instanceof CABLOCK)
          {
            long[] dimSizes = ((CABLOCK) compositionBlock).getDimSizes();
            for (long dimSize : dimSizes)
            {
              cycleCount *= dimSize;
            }
          }
        }

        ins.setLongVal("cl", cycleCount);

        // export flags
        setGlobalFlag = exportFlags(ins, idBlock, dgBlock, cgBlock, cnBlock, startOffset, cycleCount);

        // type spec is of type: dt_bit_* => write bit offset (bo) and bit count
        // (bc)
        boolean writeBitProps = vt > 26 && vt < 33;
        short bitOffset = cnBlock.getBitOffset();
        if ((bitOffset != 0 || cnBlock.getBitCount() % 8 != 0) && writeBitProps)
        {
          ins.setShortVal("bo", bitOffset);
          ins.setShortVal("bc", (short) cnBlock.getBitCount());
        }

        // bind to local column and write instance
        ins.setLongLongVal("lc", iidLc);
        ins.execute();

        // switch to next block or escape
        if (currdl == null)
        {
          currblock = -1; // just a single data block
        }
        else
        {
          // search next block in list.
          dlindex++;
          if (dlindex < currdl.getCount())
          { // more blocks in list
            currblock = currdl.getLnkDlData()[dlindex];
          }
          else
          {
            // switch to next list, and start with first block?
            if (currdl.getLnkDlNext() > 0)
            {
              currdl = currdl.getDlNextBlock();
              dlindex = 0;
              currblock = currdl.getLnkDlData()[dlindex];
            }
            else
            {
              currblock = -1;
            }
          }
        }
      }
    }
    return setGlobalFlag;
  }

  /**
   * Create a new Unit for a channel, if needed.
   * 
   * @param modelCache
   *        The ODSModelCache in use.
   * @param cnblock
   *        The Channel Block.
   * @param ccBlock
   *        The Channel's conversion block.
   * @param existingUnts
   *        Map containing Name (key) and ID (Value) of all created units.
   * @return The id of the corresponding unit.
   */
  private long writeUnit(ODSModelCache modelCache, CNBLOCK cnblock, CCBLOCK ccBlock, Map<String, Long> existingUnts)
      throws AoException, IOException
  {

    // create 'AoUnit' instance if not yet existing
    // Get unit name and metadata
    String unitName = "";
    BLOCK unitblk = cnblock.getMdUnitBlock();
    MDBLOCK unitMetadata = null;

    // Search for correct unit in channel CNBLOCK first
    if (unitblk != null)
    {
      if (unitblk instanceof MDBLOCK)
      {
        unitName = xmlParser.extractCommentText(((MDBLOCK) unitblk).getMdData());
        unitMetadata = (MDBLOCK) unitblk;
      }
      else if (unitblk instanceof TXBLOCK)
      {
        unitName = ((TXBLOCK) unitblk).getTxData().trim();
      }
    }
    else
    { // Then look in CCBLOCK
      if (ccBlock != null)
      {
        unitblk = ccBlock.getMdUnitBlock();
        if (unitblk != null)
        {
          if (unitblk instanceof MDBLOCK)
          {
            unitName = xmlParser.extractCommentText(((MDBLOCK) unitblk).getMdData());
            unitMetadata = (MDBLOCK) unitblk;
          }
          else if (unitblk instanceof TXBLOCK)
          {
            unitName = ((TXBLOCK) unitblk).getTxData().trim();
          }
        }
      }
    }

    if (unitName.length() > 0)
    {
      Long iid = existingUnts.get(unitName);
      if (iid == null)
      {
        // create unit instance
        ODSInsertStatement ins = new ODSInsertStatement(modelCache, "unt");
        ins.setStringVal("iname", unitName);
        ins.setDoubleVal("factor", 1d);
        ins.setDoubleVal("offset", 0d);
        if (unitMetadata != null)
        {
          xmlParser.writeCNCommentToUnit(ins, unitMetadata.getMdData());
        }
        iid = ins.execute();
        existingUnts.put(unitName, iid);
      }
      return iid;

    }
    return -1;
  }

  /**************************************************************************************
   * helper methods
   **************************************************************************************/

  /**
   * Get the conversion parameters of the conversion block for 1:1, linear or
   * rational conversion.
   * 
   * @param ccBlock
   *        The Conversion Block.
   * @return The parameters as Double-Array.
   * @throws AoException
   *         in case of errors
   */
  private static double[] getGenerationParameters(CCBLOCK ccBlock) throws AoException
  {
    // CCBLOCK may be null, assume explicit
    if (ccBlock == null)
    {
      return new double[0];
    }

    int formula = ccBlock.getType();

    // '1:1'
    if (formula == 0)
    {
      return new double[0];
    }
    // 'linear'
    else if (formula == 1)
    {
      return ccBlock.getValues();
    }
    // 'rational'
    else if (formula == 2)
    {
      double[] genParams = ccBlock.getValues();
      if (isRatConv2RawLinExt(ccBlock))
      {
        // sequence rep.: 'raw_linear_external'
        return new double[]
        { genParams[2], genParams[1] };
      }
      else if (isRatConv2ExtComp(ccBlock))
      {
        // sequence rep.: 'external_component'
        return new double[0];
      }
      else
      {
        throw new AoException(ErrorCode.AO_IMPLEMENTATION_PROBLEM, SeverityFlag.ERROR, 0,
            "unable write channel with rational conversion for ccBlock: " + ccBlock);
      }
    }

    // No parameters otherwise
    return new double[0];
  }

  /**
   * Writes the content of an SIBLOCK to the session.
   *
   * @param ins
   *        The insert statement to use.
   * @param siBlock
   *        The SIBLOCK.
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  private void writeSiBlock(ODSInsertStatement ins, SIBLOCK siBlock) throws AoException, IOException
  {
    // si_tx_name
    TXBLOCK txName = siBlock.getTxNameBlock();
    if (txName != null)
    {
      ins.setStringVal("src_name", txName.getTxData());
    }
    // si_tx_path
    TXBLOCK txPath = siBlock.getTxPathBlock();
    if (txPath != null)
    {
      ins.setStringVal("src_path", txPath.getTxData());
    }
    // si_md_comment
    BLOCK block = siBlock.getMdCommentBlock();
    if (block instanceof TXBLOCK)
    {
      ins.setStringVal("src_cmt", ((TXBLOCK) block).getTxData());
    }
    else if (block instanceof MDBLOCK)
    {
      xmlParser.writeSICommentToCg(ins, ((MDBLOCK) block).getMdData());
    }

    ins.setEnumVal("src_type", siBlock.getSourceType());
    ins.setEnumVal("src_bus", siBlock.getBusType());
    ins.setShortVal("src_sim", (short) (siBlock.getFlags() & 1));
  }

  /**
   * Read the name of a Channel.
   * 
   * @param cnBlock
   *        The Channel Block
   * @return The name.
   * @throws IOException
   */
  private static String readMeqName(CNBLOCK cnBlock) throws IOException
  {
    TXBLOCK nameblk = cnBlock.getCnTxNameBlock();
    String meqName = "default";
    if (nameblk != null)
    {
      meqName = nameblk.getTxData().trim();
    }
    else
    {
      LOG.warn("No channel name found!");
    }

    return meqName;
  }

  /**
   * Returns the target ASAM ODS sequence representation for the external
   * component description.<br/>
   * List of MDF4 formula types:
   * <ul>
   * <li>0 = 1:1 Conversion</li>
   * <li>1 = parametric, linear</li>
   * <li>2 = rational conversion</li>
   * <li>3 = ASAM-MCD2 Text formula</li>
   * <li>4 = tabular with interpolation</li>
   * <li>5 = tabular</li>
   * <li>6 = Value Range to Value tabular lookup</li>
   * <li>7 = Value to Text/Scale tabular lookup</li>
   * <li>8 = Value Range to Text/Scale tabular lookup</li>
   * <li>9 = Text to Value tabular lookup</li>
   * <li>10 = Text to Text tabular lookup</li>
   * </ul>
   *
   * @author Tobias Leemann
   * @return The ASAM ODS sequence representation enum value.
   * @throws ConvertException
   */
  private static int getSeqRep(CNBLOCK cnBlock, CCBLOCK ccBlock) throws AoException
  {
    // CCBLOCK may be null, assume explicit with external Component
    if (ccBlock == null)
    {
      return 7;
    }

    if (cnBlock.getChannelType() == 3)
    {
      // virtual master channel -> implicit_linear
      return 2;
    }
    int formula = ccBlock.getType();
    // '1:1 conversion formula' => external_component
    if (formula == 0)
    {
      return 7;
    }
    // 'linear' => 'raw_linear_external'
    else if (formula == 1)
    {
      return 8;
    }
    // 'rational conversion' => 'external_component'
    else if (formula == 2)
    {
      if (isRatConv2RawLinExt(ccBlock))
      {
        // redirect => 'raw_linear_external'
        return 8;
      }
      else if (isRatConv2ExtComp(ccBlock))
      {
        // manual calculation => 'external_component'
        return 7;
      }
      else
      {
        throw new AoException(ErrorCode.AO_IMPLEMENTATION_PROBLEM, SeverityFlag.ERROR, 0,
            "unable write channel with rational conversion for ccBlock: " + ccBlock);
      }
    }
    // 'Text formula' => 'external_component'
    else if (formula == 3)
    {
      LOG.error("Text formulas are not supported at the moment.");
      return 7;
    }
    // 'ALL lookup conversions' => 'external_component'
    else if (formula <= 10)
    {
      return 7;
    }
    else
    {
      LOG.warn("Unsupported Formula type " + formula);
      return 7;
    }
  }

  /**
   * Returns the target ASAM ODS external component type specification enum
   * value for a MDF4 channel description.<br/>
   * The data type is determined by the signal data type and the number of
   * bits.<br/>
   *
   * @param cnBlock
   *        The MDF3 CNBLOCK.
   * @return The ASAM ODS type specification enumeration value.
   * @throws IOException
   *         Unsupported MDF3 data type.
   */
  private static int getValueType(CNBLOCK cnBlock) throws IOException
  {
    int dt = cnBlock.getDataType();
    int nb = (int) cnBlock.getBitCount();
    int bitOffset = cnBlock.getBitOffset();

    // 0 = unsigned integer LEO
    if (dt == 0)
    {
      if (nb == 8 && bitOffset == 0)
      { // 8 bit: dt_byte
        return 1;
      }
      else if (nb == 16 && bitOffset == 0)
      { // 16 bit: dt_ushort
        return 21;
      }
      else if (nb == 32 && bitOffset == 0)
      { // 32 bit: dt_ulong
        return 23;
      }
      else if (nb == 64 && bitOffset == 0)
      { // 64 bit: dt_longlong
        return 4;
      }
      else
      { // variable bit length: dt_bit_uint
        return 29;
      }
    }

    // 1 = unsigned integer BEO
    else if (dt == 1)
    {
      if (nb == 8 && bitOffset == 0)
      { // 8 bit: dt_byte
        return 1;
      }
      else if (nb == 16 && bitOffset == 0)
      { // 16 bit: dt_ushort_beo
        return 22;
      }
      else if (nb == 32 && bitOffset == 0)
      { // 32 bit: dt_ulong_beo
        return 24;
      }
      else if (nb == 64 && bitOffset == 0)
      { // 64 bit: dt_longlong_beo
        return 9;
      }
      else
      { // variable bit length: dt_bit_uint_beo
        return 30;
      }
    }

    // 2 = signed integer LEO
    else if (dt == 2)
    {
      if (nb == 8 && bitOffset == 0)
      { // 8 bit: dt_sbyte
        return 19;
      }
      else if (nb == 16 && bitOffset == 0)
      { // 16 bit: dt_short
        return 2;
      }
      else if (nb == 32 && bitOffset == 0)
      { // 32 bit: dt_long
        return 3;
      }
      else if (nb == 64 && bitOffset == 0)
      { // 64 bit: dt_longlong
        return 4;
      }
      else
      { // variable bit length: dt_bit_int
        return 27;
      }
    }

    // 3 = signed integer BEO
    else if (dt == 3)
    {
      if (nb == 8 && bitOffset == 0)
      { // 8 bit: dt_byte
        return 1;
      }
      else if (nb == 16 && bitOffset == 0)
      { // 16 bit: dt_short_beo
        return 7;
      }
      else if (nb == 32 && bitOffset == 0)
      { // 32 bit: dt_long_beo
        return 8;
      }
      else if (nb == 64 && bitOffset == 0)
      { // 64 bit: dt_longlong_beo
        return 9;
      }
      else
      { // variable bit length: dt_bit_int_beo
        return 28;
      }
    }

    // 4 IEEE 754 floating-point format LEO
    else if (dt == 4)
    {
      if (nb == 32 && bitOffset == 0)
      { // 32 bit: ieeefloat4
        return 5;
      }
      else if (nb == 64 && bitOffset == 0)
      { // 64 bit: ieeefloat8
        return 6;
      }
      else
      { // variable bit length: dt_bit_float
        return 31;
      }
    }

    // 5 = IEEE 754 floating-point format BEO
    else if (dt == 5)
    {
      if (nb == 32 && bitOffset == 0)
      { // 32 bit: ieeefloat4_beo
        return 10;
      }
      else if (nb == 64 && bitOffset == 0)
      { // 64 bit: ieeefloat8_beo
        return 11;
      }
      else
      { // variable bit length: dt_bit_float_beo
        return 32;
      }
    }

    // 6-9 = String (NULL terminated): dt_string
    else if (dt == 6 || dt == 7 || dt == 8 || dt == 9)
    {
      return 12;
    }

    // 10 = Byte Array: dt_bytestr
    else if (dt == 10)
    {
      return 13;
    }
    else
    {
      // TODO
      LOG.warn("Data type " + dt + " is not yet supported.");
      return 13;
    }
  }

  /**
   * Returns the raw dataType for given type specification.
   *
   * @param typeSpec
   *        The TypeSpec.
   * @param cnBlock
   *        The CNBLOCK.
   * @return The raw dataType.
   * @throws AoException
   *         unable to obtain raw datatype
   */
  private static int getRawDataTypeForValueType(int typeSpec, CNBLOCK cnBlock) throws AoException
  {
    if (cnBlock.getChannelType() == 3)
    {
      // virtual master channel (implicit linear), calculated with generation
      // parameters
      return 7;
    }

    int ret = 0;
    if (typeSpec == 0)
    { // dt_boolean
      ret = 4; // DT_BOOLEAN
    }
    else if (typeSpec == 1)
    { // dt_byte
      ret = 5; // DT_BYTE
    }
    else if (typeSpec == 2)
    { // dt_short
      ret = 2; // DT_SHORT
    }
    else if (typeSpec == 3)
    { // dt_long
      ret = 6; // DT_LONG
    }
    else if (typeSpec == 4)
    { // dt_longlong
      ret = 8; // DT_LONGLONG
    }
    else if (typeSpec == 5)
    { // ieeefloat4
      ret = 3; // DT_FLOAT
    }
    else if (typeSpec == 6)
    { // ieeefloat8
      ret = 7; // DT_DOUBLE
    }
    else if (typeSpec == 7)
    { // dt_short_beo
      ret = 2; // DT_SHORT
    }
    else if (typeSpec == 8)
    { // dt_long_beo
      ret = 6; // DT_LONG
    }
    else if (typeSpec == 9)
    { // dt_longlong_beo
      ret = 8; // DT_LONGLONG
    }
    else if (typeSpec == 10)
    { // ieeefloat4_beo
      ret = 3; // DT_FLOAT
    }
    else if (typeSpec == 11)
    { // ieeefloat8_beo
      ret = 7; // DT_DOUBLE
    }
    else if (typeSpec == 12)
    { // dt_string
      ret = 1; // DT_STRING
    }
    else if (typeSpec == 13)
    { // dt_bytestr
      ret = 11; // DT_BYTESTR
    }
    else if (typeSpec == 14)
    { // dt_blob
      ret = 12; // DT_BLOB
    }
    else if (typeSpec == 15)
    { // dt_boolean_flags_beo
      ret = 4; // DT_BOOLEAN
    }
    else if (typeSpec == 16)
    { // dt_byte_flags_beo
      ret = 5; // DT_BYTE
    }
    else if (typeSpec == 17)
    { // dt_string_flags_beo
      ret = 1; // DT_STRING
    }
    else if (typeSpec == 18)
    { // dt_bytestr_beo
      ret = 11; // DT_BYTESTR
    }
    else if (typeSpec == 19)
    { // dt_sbyte
      ret = 2; // DT_SHORT
    }
    else if (typeSpec == 20)
    { // dt_sbyte_flags_beo
      ret = 2; // DT_SHORT
    }
    else if (typeSpec == 21)
    { // dt_ushort
      ret = 6; // DT_LONG
    }
    else if (typeSpec == 22)
    { // dt_ushort_beo
      ret = 6; // DT_LONG
    }
    else if (typeSpec == 23)
    { // dt_ulong
      ret = 8; // DT_LONGLONG
    }
    else if (typeSpec == 24)
    { // dt_ulong_beo
      ret = 8; // DT_LONGLONG
    }
    else if (typeSpec == 25)
    { // dt_string_utf8
      ret = 1; // DT_STRING
    }
    else if (typeSpec == 26)
    { // dt_string_utf8_beo
      ret = 1; // DT_STRING
    }
    // dt_bit_int [27], dt_bit_int_beo [28], dt_bit_uint [29],
    // dt_bit_uint_beo [30]
    else if (typeSpec == 27 || typeSpec == 28 || typeSpec == 29 || typeSpec == 30)
    {
      int dt = cnBlock.getDataType();
      int nb = (int) cnBlock.getBitCount();
      if ((dt == 0 || dt == 1) && nb >= 1 && nb <= 8)
      { // unsigned byte
        ret = 5; // DT_BYTE
      }
      else if ((dt == 2 || dt == 3) && nb >= 1 && nb <= 8)
      { // signed
        // byte
        ret = 5; // DT_BYTE
      }
      else if ((dt == 0 || dt == 1) && nb >= 9 && nb <= 16)
      { // unsigned
        // short
        ret = 6; // DT_LONG
      }
      else if ((dt == 2 || dt == 3) && nb >= 9 && nb <= 16)
      { // signed
        // short
        ret = 2; // DT_SHORT
      }
      else if ((dt == 0 || dt == 1) && nb >= 17 && nb <= 32)
      { // unsigned
        // int
        ret = 8; // DT_LONGLONG
      }
      else if ((dt == 2 || dt == 3) && nb >= 17 && nb <= 32)
      { // int
        ret = 6; // DT_LONG
      }
      else if ((dt == 0 || dt == 1) && nb >= 33)
      { // unsigned int >32
        // bit
        ret = 8; // DT_LONGLONG
      }
      else if ((dt == 2 || dt == 3) && nb >= 33)
      { // signed int >32 bit
        ret = 8; // DT_LONGLONG
      }
    }
    // dt_bit_float [31], dt_bit_float_beo [32]
    else if (typeSpec == 31 || typeSpec == 32)
    {
      int dt = cnBlock.getDataType();
      int nb = (int) cnBlock.getBitCount();
      if ((dt == 2 || dt == 3 || dt == 11 || dt == 12 || dt == 15 || dt == 16) && (nb == 16 || nb == 32))
      { // half precision floating point, ieeefloat4,
        // ieeefloat4_beo
        ret = 3; // DT_FLOAT
      }
      else if ((dt == 2 || dt == 3 || dt == 11 || dt == 12 || dt == 15 || dt == 16) && nb == 64)
      { // ieeefloat8,
        // ieeefloat8_beo
        ret = 7; // DT_DOUBLE
      }
      // TODO Non-IEEE floats
    }
    // not found!
    else
    {
      throw new AoException(ErrorCode.AO_BAD_PARAMETER, SeverityFlag.ERROR, 0, "Unsupported typeSpec: " + typeSpec);
    }
    return ret;
  }

  /**
   * Returns the target ASAM ODS measurement quantity data type for a MDF4
   * channel description.<br/>
   * The data type is determined by the formula, the signal data type and the
   * number of bits.
   *
   * @param expandDataType
   *        Indicates whether to expand data type or not.
   * @param cnBlock
   *        The MDF CNBLOCK.
   * @param ccBlock
   *        The MDF CCBLOCK.
   * @return The ASAM ODS data type.
   * @throws IOException
   *         Unable to determine data type.
   * @throws AoException
   *         in case of errors
   */
  private static int getDataType(boolean expandDataType, CNBLOCK cnBlock, CCBLOCK ccBlock)
      throws IOException, AoException
  {
    // CCBLOCK may be null, assume 1:1
    int formula = 0;
    if (ccBlock != null)
    {
      formula = ccBlock.getType();
    }

    if (cnBlock.getChannelType() == 3)
    {
      // virtual master channel (implicit linear), calculated with generation
      // parameters
      return 7;
    }

    int dt = cnBlock.getDataType();
    int nb = (int) cnBlock.getBitCount();

    // STRING
    if (dt >= 6 && dt <= 9)
    {
      return 1; // DT_STRING
    }

    // 1 = parametric, linear
    if (formula == 1)
    {
      if (nb == 0)
      {
        // virtual data channel that specifies a linear conversion,
        // chapter 4.16 specifies them to have cn_data_type=0, cn_bit_count=0
        // and a linear conversion rule; it will be mapped to DT_LONGONG, the
        // only ODS datatype capable of storing the unsigned integer value range
        return 8; // DT_LONGLONG
      }
      else if (nb == 1)
      {
        // 1 bit should be DT_BOOLEAN, but most of tools do not support
        // this
        return 5; // DT_BYTE
      }
      else if (nb >= 2 && nb <= 32)
      {
        return 3; // DT_FLOAT
      }
      else if (nb >= 33 && nb <= 64)
      {
        return 7; // DT_DOUBLE
      }
    }
    // 2 = rational conversion
    else if (formula == 2)
    {
      // values are calculated either way with real (64 bit ieee-754)
      // double values no matter how many bits are used for internal
      // values, therefore it is safe to return DT_DOUBLE here
      return 7; // DT_DOUBLE
    }

    // 0= 1:1 conversion formula (Int = Phys)
    else if (formula == 0)
    {
      if (dt == 10)
      { // ByteArray data
        return 11; // DT_BYTESTR
      }
      else if (dt <= 9 && dt >= 6)
      { // STRING (6-9)
        return 1; // DT_STRING
      }
      else if ((dt == 0 || dt == 1) && nb >= 1 && nb <= 8)
      { // dt_byte
        return expandDataType ? 3 : 5; // [DT_FLOAT] DT_BYTE
      }
      else if ((dt == 2 || dt == 3) && nb >= 1 && nb <= 8)
      { // dt_sbyte
        return expandDataType ? 3 : 2; // [DT_FLOAT] DT_SHORT
      }
      else if ((dt == 0 || dt == 1) && nb >= 9 && nb <= 16)
      { // dt_ushort,
        // dt_ushort_beo
        return expandDataType ? 3 : 6; // [DT_FLOAT] DT_LONG
      }
      else if ((dt == 2 || dt == 3) && nb >= 9 && nb <= 16)
      { // dt_short,
        // dt_short_beo
        return expandDataType ? 3 : 2; // [DT_FLOAT] DT_SHORT
      }
      else if ((dt == 0 || dt == 1) && nb >= 17 && nb <= 32)
      { // dt_ulong,
        // dt_ulong_beo
        return expandDataType ? 7 : 8; // [DT_DOUBLE] DT_LONGLONG
      }
      else if ((dt == 2 || dt == 3) && nb >= 17 && nb <= 32)
      { // dt_long,
        // dt_long_beo
        return expandDataType ? 3 : 6; // [DT_FLOAT] DT_LONG
      }
      else if ((dt == 0 || dt == 1) && nb >= 33)
      { // unsigned int >32
        // bit
        return expandDataType ? 7 : 8; // [DT_DOUBLE] DT_LONGLONG
      }
      else if ((dt == 2 || dt == 3) && nb >= 33 && nb <= 64)
      { // dt_longlong,
        // dt_longlong_beo
        return expandDataType ? 7 : 8; // [DT_DOUBLE] DT_LONGLONG
      }
      else if ((dt == 4 || dt == 5) && nb == 16)
      { // half precision floating point
        return 3; // DT_FLOAT
      }
      else if ((dt == 4 || dt == 5) && nb == 32)
      { // ieeefloat4,
        // ieeefloat4_beo
        return 3; // DT_FLOAT
      }
      else if ((dt == 4 || dt == 5) && nb == 64)
      { // ieeefloat8,
        // ieeefloat8_beo
        return 7; // DT_DOUBLE
      }
    }
    else if (formula == 9 || formula == 10)
    { // X to text
      return 1; // DT_STRING
    }
    else if (formula == 4 || formula == 5 || formula == 6)
    {
      return 7; // DT_DOUBLE
    }
    else if (formula == 7 || formula == 8)
    {
      return getRawDataTypeForValueType(getValueType(cnBlock), cnBlock);
    }

    throw new IOException("Unsupported MDF4 datatype: " + cnBlock + "\n " + ccBlock);
  }

  /**
   * Checks whether channel with rational conversion may be stored as a
   * 'raw_linear_external'.
   * <p>
   * NOTE: This is a workaround to provide channels with formula == 2 with a
   * reduced set of generation parameters. Such channel values are described
   * with a rational conversion, which can not be described in ODS. To do so the
   * generation parameters p1, p3 and p4 must be ZERO and p5 must be ONE.
   * <p>
   * <b>ATTENTION: THIS IS JUST A WORKAROUND UND HAS TO BE REMOVED AS SOON AS IT
   * IS POSSIBLE TO DESCRIBE SUCH CHANNELS IN ODS!</b>
   *
   * @param ccBlock
   *        the conversion block
   * @return true if the values must be calculated and stored in an external
   *         file
   */
  @Deprecated
  private static boolean isRatConv2RawLinExt(CCBLOCK ccBlock)
  {
    if (ccBlock == null)
    {
      return false;
    }
    else if (ccBlock.getType() == 2)
    {
      // rational conversion
      double[] genParams = ccBlock.getValues();
      if (genParams == null || genParams.length != 6)
      {
        return false;
      }
      else
      {
        boolean p1Zero = Double.compare(genParams[0], 0D) == 0;
        boolean p4Zero = Double.compare(genParams[3], 0D) == 0;
        boolean p5Zero = Double.compare(genParams[4], 0D) == 0;
        boolean p6One = Double.compare(genParams[5], 1D) == 0;
        return p1Zero && p4Zero && p5Zero && p6One;
      }
    }

    return false;
  }

  /**
   * Checks whether channel with rational conversion may be stored as a
   * 'external_component'.
   * <p>
   * NOTE: This is a workaround to provide channels with formula == 2. Such
   * channel values are described with a rational conversion, which can not be
   * described in ODS. Therefore the whole value sequence is calculated and
   * referenced as an 'external_component'.
   * <p>
   * <b>ATTENTION: THIS IS JUST A WORKAROUND UND HAS TO BE REMOVED AS SOON AS IT
   * IS POSSIBLE TO DESCRIBE SUCH CHANNELS IN ODS!</b>
   *
   * @param ccBlock
   *        the conversion block
   * @return true if the values must be calculated and stored in an external
   *         file
   */
  @Deprecated
  private static boolean isRatConv2ExtComp(CCBLOCK ccBlock)
  {
    if (ccBlock == null)
    {
      return false;
    }
    else if (ccBlock.getType() == 2)
    {
      // rational conversion
      double[] genParams = ccBlock.getValues();
      if (genParams == null || genParams.length != 6)
      {
        return false;
      }
      else
      {
        boolean p1Zero = Double.compare(genParams[0], 0D) != 0;
        boolean p4Zero = Double.compare(genParams[3], 0D) != 0;
        boolean p5Zero = Double.compare(genParams[4], 0D) != 0;
        boolean p6One = Double.compare(genParams[5], 1D) != 0;
        return p1Zero || p4Zero || p5Zero || p6One;
      }
    }

    return false;
  }

  /**
   * Write the instances of 'AoExternalComponent'.
   * <p>
   * One instance is written for all calculated vaues.
   * <p>
   * NOTE: This is a workaround to provide channels with formula == 2. Such
   * channel values are described with a rational conversion, which can not be
   * described in ODS. Therefore the whole value sequence is calculated and
   * referenced as an 'external_component'.
   * <p>
   * <b>ATTENTION: THIS IS JUST A WORKAROUND UND HAS TO BE REMOVED AS SOON AS IT
   * IS POSSIBLE TO DESCRIBE SUCH CHANNELS IN ODS!</b>
   *
   * @param modelCache
   *        The application model cache.
   * @param iidLc
   *        The instance id of the 'AoLocalColumn' instance.
   * @param idBlock
   *        The IDBLOCK.
   * @param dgBlock
   *        The DGBLOCK.
   * @param cgBlock
   *        The CGBLOCK.
   * @param cnBlock
   *        The CNBLOCK.
   * @param ccBlock
   *        The CCBLOCK.
   * @param sectionstart
   *        The link to data, can be a DL, RD or DT Block or HL, DZ, but these
   *        are not supported.
   * @param parity
   *        Used for previews, where only each third record has to be addressed.
   *        If every record will be addressed, parity has to be set to 0.
   *        Otherwise valid values are 1, 2 and 3. (e.g. if parity==1 the first
   *        of each three records will be addressed)
   *
   * @return true, if the global flag of the channel has to be set to valid, false for invalid, null otherwise
   * @throws AoException
   *         Error writing to session.
   * @throws IOException
   *         Error reading from MDF file.
   */
  @Deprecated
  private Boolean createCustomRatConvEC(ODSModelCache modelCache, long iidLc, IDBLOCK idBlock, DGBLOCK dgBlock,
      CGBLOCK cgBlock, CNBLOCK cnBlock, CCBLOCK ccBlock, long sectionstart, int parity) throws AoException, IOException
  {
    if (parity != 0)
    {
      throw new AoException(ErrorCode.AO_BAD_PARAMETER, SeverityFlag.ERROR, 0,
          "channel preview with formula == 2 (rational conversion) is currently not supported");
    }

    DLBLOCK currdl = null; // current list block
    int dlindex = 0; // index in data list block.
    long currblock = -1;

    switch (BLOCK.getBlockType(idBlock.sbc, sectionstart))
    {
    case "##DT":
    case "##RD":
      currblock = sectionstart;
      break;
    case "##DL":
      currdl = DLBLOCK.read(idBlock.sbc, sectionstart);
      currblock = currdl.getLnkDlData()[0];
      // perform check for records over blockborders.
      if (currdl.breaksRecords(cgBlock.getDataBytes() + dgBlock.getRecIdSize() + cgBlock.getInvalBytes()))
      {
        throw new IOException("This data list cannot be read because records are splitted.");
      }
      break;
    case "##DZ":
    case "##HL":
      throw new IOException("Zipped blocks cannot be parsed into the ODS-Format.");
    }

    if (currblock < 0)
    {
      return null;
    }

    if (customRatConfPath == null)
    {
      customRatConfPath = idBlock.getMdfFilePath().resolveSibling("rational_conversion.calc");
      if (!Files.exists(customRatConfPath))
      {
        Files.createFile(customRatConfPath);
      }
    }

    Boolean setGlobalFlag = null;
    try (SeekableByteChannel channel = Files.newByteChannel(customRatConfPath, StandardOpenOption.APPEND))
    {
      ByteBuffer writeBuffer = ByteBuffer.wrap(new byte[8]);
      writeBuffer.order(ByteOrder.LITTLE_ENDIAN);
      long startOffset = channel.position();
      long count = 0;
      while (currblock != -1)
      {
        long vo = dgBlock.getRecIdSize() + cnBlock.getByteOffset() + cnBlock.getBitOffset() / 8;
        long recSizeWoInval = cgBlock.getDataBytes() + dgBlock.getRecIdSize();
        long bs = recSizeWoInval + cgBlock.getInvalBytes();
        long so = currblock + 24L;

        int cl;
        if (BLOCK.getBlockType(idBlock.sbc, currblock).equals(DTBLOCK.BLOCK_ID))
        {
          cl = (int) ((DTBLOCK.read(idBlock.sbc, currblock).getLength() - 24) / bs);
        }
        else if (BLOCK.getBlockType(idBlock.sbc, currblock).equals(RDBLOCK.BLOCK_ID))
        {
          cl = (int) ((RDBLOCK.read(idBlock.sbc, currblock).getLength() - 24) / bs);
        }
        else
        {
          throw new AoException(ErrorCode.AO_BAD_PARAMETER, SeverityFlag.ERROR, 0,
              "component length 'cl' is not allowed to be unknown");
        }

        short bo = cnBlock.getBitOffset();
        short bc = bo != 0 && cnBlock.getBitCount() % 8 != 0 ? (short) cnBlock.getBitCount() : 0;
        double[] p = ccBlock.getValues();

        if (bo != 0 || bc != 0 || cnBlock.getBitCount() % 8 != 0)
        {
          throw new AoException(ErrorCode.AO_BAD_PARAMETER, SeverityFlag.ERROR, 0,
              "bit count '" + bc + "' and bit offset '" + bo + "' is not supported for custom ration conversion");
        }

        int bits = (int) cnBlock.getBitCount();
        int dt = cnBlock.getDataType();
        boolean isInteger = dt > -1 && dt < 4;
        boolean isReal = dt > 3 && dt < 6;
        boolean isUnsigned = dt == 0 || dt == 1;
        ByteOrder byteOrder = dt == 1 || dt == 3 || dt == 5 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
        for (int i = 0; i < cl; i++)
        {
          idBlock.sbc.position(so + i * bs + vo);
          ByteBuffer byteBuffer = ByteBuffer.allocate(bits / 8);
          byteBuffer.order(byteOrder);
          idBlock.sbc.read(byteBuffer);
          byteBuffer.rewind();

          double internal = 0;
          if (isInteger)
          {
            if (bits == 8)
            {
              // isUnsigned ? short : byte
              internal = isUnsigned ? byteBuffer.get() & 0xFF : byteBuffer.get();
            }
            else if (bits == 16)
            {
              // isUnsigned ? int : short
              internal = isUnsigned ? byteBuffer.getShort() & 0xFFFF : byteBuffer.getShort();
            }
            else if (bits == 32)
            {
              // isUnsigned ? long : int
              internal = isUnsigned ? byteBuffer.getInt() & 0xFFFFFFFF : byteBuffer.getInt();
            }
            else if (bits == 64)
            {
              if (isUnsigned)
              {
                throw new AoException(ErrorCode.AO_BAD_PARAMETER, SeverityFlag.ERROR, 0,
                    "reading unsigned 64 bit integeres is not implemented");
              }
              // to support unsigned 64 bit, BigInteger has to be
              // used -> performance costs
              internal = byteBuffer.getLong();
            }
            else
            {
              String unsigned = isUnsigned ? "unsigned" : "signed";
              throw new AoException(ErrorCode.AO_BAD_PARAMETER, SeverityFlag.ERROR, 0,
                  "customized reading of '" + bits + "' bit '" + unsigned + "' intergers is not implemented");
            }
          }
          else if (isReal)
          {
            if (bits == 32)
            {
              // ieee754 floating point
              internal = byteBuffer.getFloat();
            }
            else if (bits == 64)
            {
              // ieee754 floating point
              internal = byteBuffer.getDouble();
            }
            else
            {
              String unsigned = isUnsigned ? "unsigned" : "signed";
              throw new AoException(ErrorCode.AO_BAD_PARAMETER, SeverityFlag.ERROR, 0,
                  "customized reading of '" + bits + "' bit '" + unsigned + "' real is not implemented");
            }
          }
          else
          {
            throw new AoException(ErrorCode.AO_BAD_PARAMETER, SeverityFlag.ERROR, 0,
                "given value is neither an integer nor a real number");
          }
          double phys = (p[0] * Math.pow(internal, 2) + p[1] * internal + p[2])
              / (p[3] * Math.pow(internal, 2) + p[4] * internal + p[5]);

          writeBuffer.putDouble(phys);
          writeBuffer.rewind();
          channel.write(writeBuffer);
          writeBuffer.rewind();
          count++;
        }

        // switch to next block or escape
        if (currdl == null)
        {
          currblock = -1; // just a single data block
        }
        else
        {
          // search next block in list.
          dlindex++;
          if (dlindex < currdl.getCount())
          { // more blocks in list
            currblock = currdl.getLnkDlData()[dlindex];
          }
          else
          {
            // switch to next list, and start with first block?
            if (currdl.getLnkDlNext() > 0)
            {
              currdl = currdl.getDlNextBlock();
              dlindex = 0;
              currblock = currdl.getLnkDlData()[dlindex];
            }
            else
            {
              currblock = -1;
            }
          }
        }

        // switch to next block or escape
        if (currdl == null)
        {
          currblock = -1; // just a single data block
        }
        else
        {
          // search next block in list.
          dlindex++;
          if (dlindex < currdl.getCount())
          { // more blocks in list
            currblock = currdl.getLnkDlData()[dlindex];
          }
          else
          {
            // switch to next list, and start with first block?
            if (currdl.getLnkDlNext() > 0)
            {
              currdl = currdl.getDlNextBlock();
              dlindex = 0;
              currblock = currdl.getLnkDlData()[dlindex];
            }
            else
            {
              currblock = -1;
            }
          }
        }
      }

      if (count < 0 || count != (int) count || count * 8 > Integer.MAX_VALUE)
      {
        throw new AoException(ErrorCode.AO_IMPLEMENTATION_PROBLEM, SeverityFlag.ERROR, 0,
            "value count exceeded max supported block size supported by ODS");
      }

      // values have been calculated and written to an external file
      ODSInsertStatement ins = new ODSInsertStatement(modelCache, "ec");
      ins.setStringVal("iname", "ec_custom_rat_conv");
      ins.setLongVal("cl", (int) count);
      ins.setEnumVal("vt", 6); // ieeefloat8 (little endian; 11 would be
      // big endian)
      ins.setLongLongVal("so", startOffset);
      ins.setLongVal("bs", (int) count * 8);
      ins.setLongVal("vb", (int) count);
      ins.setLongVal("vo", 0);
      ins.setStringVal("fl", customRatConfPath.getFileName().toString());
      ins.setLongLongVal("lc", iidLc);

      // export flags
      setGlobalFlag = exportFlags(ins, idBlock, dgBlock, cgBlock, cnBlock, startOffset, count);

      ins.execute();
    }
    return setGlobalFlag;
  }

  /**
   * Exports ODS compliant flags into a separate file if needed. If a global
   * flag can be set it is returned (true=valid, false=invalid) rather than
   * written to the file. That flag needs to be set to the parent local column
   * afterwards!
   *
   * @param ins
   *        flag file an start offset will be added if flags were written to
   *        file, not null
   * @param idBlock
   *        the {@link IDBLOCK}, not null
   * @param dgBlock
   *        the {@link DGBLOCK}, not null
   * @param cgBlock
   *        the {@link CGBLOCK}, not null
   * @param cnBlock
   *        the {@link CNBLOCK}, not null
   * @param startOffset
   *        start of the next record
   * @param count
   *        how many records to read
   *        
   * @return true, if all flags are valid, so the global flag can be set instead
   *         of writing flag values to the flags file. False if all flags are
   *         invalid. Null is returned, if flags were written to file.
   * @throws IOException
   *         in case of errors
   */
  private Boolean exportFlags(ODSInsertStatement ins, IDBLOCK idBlock, DGBLOCK dgBlock, CGBLOCK cgBlock,
      CNBLOCK cnBlock, long startOffset, long count) throws IOException
  {
    Boolean retVal = null;
    if ((cnBlock.getFlags() & 0x02) == 0 || cnBlock.getInvalBitPos() < 1 || count < 1)
    {
      // either invalidation bit not set or deactivated or no values available
      // -> nothing to do
      return retVal;
    }

    try (SeekableByteChannel flagsChannel = loadFlagsFileChannel(idBlock))
    {
      // to check whether a global flag can be set instead of writing the flags
      // all to the file, all of them need to be analyzed first
      /**
       * For long channels the flags are cached in bulks until it is clear
       * whether to write them to file or set a global flag
       */
      List<ByteBuffer> flagBulks = new ArrayList<>();
      /**
       * To reduce memory footprint, the index of a bulk of identical flags will
       * be mapped here to the common flag
       */
      Map<Integer, Boolean> listIndex2Flag = new HashMap<>();

      int dt = cnBlock.getDataType();
      ByteOrder byteOrder = dt == 1 || dt == 3 || dt == 5 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
      int recordSize = (int) (dgBlock.getRecIdSize() + cgBlock.getDataBytes() + cgBlock.getInvalBytes());
      int flabBytesOffset = (int) (dgBlock.getRecIdSize() + cgBlock.getDataBytes() + (cnBlock.getInvalBitPos() >> 3));
      int bitOffset = ((int) cnBlock.getInvalBitPos()) & 0x07;
      idBlock.sbc.position(startOffset);

      readAndStoreFlagsFromRecords(idBlock.sbc, byteOrder, count, recordSize, flabBytesOffset, bitOffset, flagBulks,
          listIndex2Flag);

      // check if a global flag could be set
      Boolean globalFlagToSet = analyzeGlobalFlagToSet(flagBulks, listIndex2Flag);
      if (globalFlagToSet != null)
      {
        retVal = globalFlagToSet;
      }
      // otherwise write flags to file and update insert statement
      else
      {
        ins.setStringVal("ffl", flagFile.getFileName().toString());
        ins.setLongLongVal("fso", flagsChannel.position());
        writeFlagsToFile(flagsChannel, flagBulks, listIndex2Flag);
      }
    }
    return retVal;
  }

  /**
   * Reads records from the given channel, extracts the flags and writes them
   * into the given storage structures. Reads bulks of records rather than
   * single records or even single flags from the channel for performance
   * reasons.
   * 
   * Note: Bulk reading records and extracting their flags in code massively
   * reduces the handling time of the flags compared to the (previously
   * implemented) read of one flag after another.
   * 
   * @param sourceChannel
   *        the channel of the source file set to the starting position for
   *        reading the records
   * @param byteOrder
   *        the ByteOrder to use for the buffers
   * @param overallNrOfRecords
   *        the overall number of records to read and extract their flags
   * @param recordSize
   *        the size of a single record entry (id, data, invalBit)
   * @param flabBytesOffset
   *        the byte offset in a record to read the ivalBit from
   * @param bitOffset
   *        the bit offset of the channel
   * @param flagBulks
   *        the list to fill with the ByteBuffers of each read bulk of flags
   * @param listIndex2Flag
   *        the map to write the common flag to for each bulk list index
   * @throws IOException
   *         on buffer read errors
   */
  private void readAndStoreFlagsFromRecords(SeekableByteChannel sourceChannel, ByteOrder byteOrder,
      long overallNrOfRecords, int recordSize, int flabBytesOffset, int bitOffset, List<ByteBuffer> flagBulks,
      Map<Integer, Boolean> listIndex2Flag) throws IOException
  {
    ByteBuffer flagsBuffer = ByteBuffer.allocate(FLAGS_BUFFER_SIZE);
    flagsBuffer.order(byteOrder);
    ByteBuffer bb = ByteBuffer.allocate(recordSize * MAX_RECORDS_PER_FLAGS_READ);
    bb.order(byteOrder);

    Boolean validFlagForCurrentBulk = null;
    boolean sameFlagForCurrentBulk = true;
    int bulkIndex = 0;

    long recordCounter = 0;
    while (recordCounter < overallNrOfRecords)
    {
      // read MAX_RECORDS_PER_FLAGS_READ records
      bb.rewind();
      int bytesRead = sourceChannel.read(bb);
      int recordsRead = (int) Math.min(overallNrOfRecords - recordCounter, bytesRead / recordSize);
      recordCounter += recordsRead;
      bb.rewind();

      // read each record from the buffer and extract flag
      for (int k = 0; k < recordsRead; k++)
      {
        // extract from record and convert flag to ODS flag and add to write
        // buffer
        byte[] recordBytes = new byte[recordSize];
        bb.get(recordBytes);
        byte flagByte = recordBytes[flabBytesOffset];
        short flag = ((flagByte & 0xff) & (1 << bitOffset)) != 0 ? 0 : (short) 15;
        flagsBuffer.putShort(flag);

        // check each record's flag against the other flags of current bulk
        if (validFlagForCurrentBulk == null)
        {
          validFlagForCurrentBulk = flag == (short) 15;
        }
        else if ((flag != (short) 15 && validFlagForCurrentBulk) || (flag == (short) 15 && !validFlagForCurrentBulk))
        {
          sameFlagForCurrentBulk = false;
        }

        // prepare flags bulk
        if (flagsBuffer.position() % FLAGS_BUFFER_SIZE == 0)
        {
          if (sameFlagForCurrentBulk)
          {
            // if same flags in current bulk, save this flag for bulk index and
            // set null in flagBulks
            flagBulks.add(null);
            listIndex2Flag.put(bulkIndex, validFlagForCurrentBulk);
            flagsBuffer.rewind();
          }
          else
          {
            // if different flags read in current bulk, store the current
            // bytebuffer to write flags to file at the end
            flagBulks.add(flagsBuffer);
            flagsBuffer = ByteBuffer.allocate(FLAGS_BUFFER_SIZE);
            flagsBuffer.order(byteOrder);
          }

          bulkIndex++;
          validFlagForCurrentBulk = null;
          sameFlagForCurrentBulk = true;
        }
      }
    }

    // prepare remaining flags
    if (flagsBuffer.position() > 0)
    {
      // since the last bulk of flags' length may likely differ from the
      // MAX_RECORDS_PER_FLAGS_READ it always has to be stored, in order to have
      // the correct number of flags written to the file at the end, in case
      int pos = flagsBuffer.position();
      flagsBuffer.rewind();
      flagsBuffer.limit(pos);
      flagBulks.add(flagsBuffer);

      if (sameFlagForCurrentBulk)
      {
        // if same flags in current bulk, save this flag for bulk index as well
        listIndex2Flag.put(bulkIndex, validFlagForCurrentBulk);
      }
    }
  }

  /**
   * @param flagBulks
   * @param listIndex2Flag
   * @return
   */
  private Boolean analyzeGlobalFlagToSet(List<ByteBuffer> flagBulks, Map<Integer, Boolean> listIndex2Flag)
  {
    boolean setGlobalFlag = true;
    Boolean globalFlagToSet = null;
    for (int i = 0; i < flagBulks.size(); i++)
    {
      ByteBuffer buffer = flagBulks.get(i);
      if (buffer != null && listIndex2Flag.get(i) == null)
      {
        // All homogeneous flag bulks are set to null, so if there is at least
        // one, that was not set to null (i.e. contains valid and invalid
        // values), no global flag can be set to the whole channel.
        // Important note: the last bulk's buffer is always written to the list,
        // but its common flag in the map may be set to true/false, if this last
        // bulk also contains only the same flag
        setGlobalFlag = false;
        break;
      }
      else
      {
        Boolean bulkFlag = listIndex2Flag.get(i);
        if (bulkFlag != null)
        {
          if (globalFlagToSet == null)
          {
            globalFlagToSet = bulkFlag;
          }
          else if (!globalFlagToSet.equals(bulkFlag))
          {
            // if by coincidence there are bulks which all contain the same
            // value, but some all valid and others all invalid, this is checked
            // here and no global flag can be set for the channel, but this
            // should be a very rare border case
            setGlobalFlag = false;
            break;
          }
        }
      }
    }

    Boolean retVal = null;
    if (setGlobalFlag)
    {
      retVal = globalFlagToSet;
    }
    return retVal;
  }

  /**
   * @param flagsChannel
   * @param flagBulks
   * @param listIndex2Flag
   * @throws IOException
   */
  private void writeFlagsToFile(SeekableByteChannel flagsChannel, List<ByteBuffer> flagBulks,
      Map<Integer, Boolean> listIndex2Flag) throws IOException
  {
    for (int i = 0; i < flagBulks.size(); i++)
    {
      ByteBuffer buffer = flagBulks.get(i);
      if (buffer == null)
      {
        // one or more of the bulks could be homogeneously the same flag,
        // while some may contain valid and invalid values at the same time,
        // therefore the homogeneous bulks need to be handled here
        Boolean bulkFlag = listIndex2Flag.get(i);
        if (bulkFlag != null)
        {
          // Homogeneous bulks' buffers always have a length of
          // MAX_RECORDS_PER_FLAGS_READ, since the last bulk (that may deviate
          // from that length) is always written to the buffer list and 'buffer'
          // here is not null in that case
          short[] flags = new short[MAX_RECORDS_PER_FLAGS_READ];
          Arrays.fill(flags, bulkFlag ? (short) 15 : (short) 0);
          buffer = ByteBuffer.wrap(shortToByteArray(flags));
        }
      }
      
      // write flags from buffer to the flags file channel
      if (buffer != null)
      {
        buffer.rewind();
        flagsChannel.write(buffer);
      }
    }
  }
  
  private byte[] shortToByteArray(short[] input)
  {
    int shortIndex = 0;
    int byteIndex = 0;
    int iterations = input.length;
    byte[] buffer = new byte[input.length * 2];
    
    while (shortIndex != iterations) {
      buffer[byteIndex] = (byte) (input[shortIndex] & 0x00FF); 
      buffer[byteIndex + 1] = (byte) ((input[shortIndex] & 0xFF00) >> 8);
      ++shortIndex;
      byteIndex += 2;
    }
    return buffer;
  }

  /**
   * Creates a {@link SeekableByteChannel} for the flags file.
   *
   * @param idBlock
   *        used to resolve target flags file, not null
   * @return the {@link SeekableByteChannel}, not null
   * @throws IOException
   *         if unable to create a flags file
   */
  private SeekableByteChannel loadFlagsFileChannel(IDBLOCK idBlock) throws IOException
  {
    if (flagFile == null)
    {
      flagFile = idBlock.getMdfFilePath().resolveSibling("flags.bin");
      while (Files.exists(flagFile))
      {
        flagFile = flagFile.resolveSibling("flags_" + UUID.randomUUID().toString().split("-")[0] + ".bin");
      }

      Files.createFile(flagFile);
    }

    return Files.newByteChannel(flagFile, StandardOpenOption.APPEND);
  }

}
