Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

An Nhax NHAX file is a file format that is used to export/import data from Noah.

A Nhax NHAX file is mix of binary data and XML formatted data the so called sections. As the Nhax NHAX format is complex and hard to implement HIMSA has developed a standalone library that can be used by business system developers that must support the Nhax NHAX format.

Extension to Old Nhax NHAX Format

The data in Nhax NHAX sections is defined using XSD files. All data must validate with respect to the XSD when reading/writing Nhax NHAX files.

The Misc section is now used and is defined in and XSD file.

Link to binary Nhax NHAX format: Noah 4 Extended Native Format (Nhax and Enhax)

Link to XML Sections in Nhax NHAX Files: XML Sections in Nhax Files

...

Furthermore functions may throw exceptions.

Nhax NHAX Writer

The Nhax NHAX writer writes Noah data to a Nhax NHAX file or a stream. When writing data to a file the NhaxWriter NHAXWriter will either produce a number of files of a given max size or one file that contains all data or all data written to a stream.

/// <summary>
/// Write all data to one Nhax NHAX file.
/// </summary>
/// <param name="fullPath">Full path to Nhax NHAX file</param>
/// <param name="password">Password to access the file</param>
/// <param name="nhaxFileCreatedCallback">Function called when Nhax NHAX file is written. The function is called with the name of the file that is written. Can be set to null.</param>
/// <param name="overwriteExistingFiles">True existing files will be overwritten. If false an error will be reported if file exists.</param>
/// <param name="compressData">If true data are compressed</param>
public NhaxWriter(string fullPath, string password, NhaxFileCreatedCallback nhaxFileCreatedCallback = null, bool overwriteExistingFiles = false, bool compressData = true)

...

/// <summary>
/// NhaxWriter constructor that writes data to one or more Nhax NHAX files.
/// If more than one Nhax NHAX file are created the file will contain a Misc section containing al Misc data provided. The user section will only contain users that are referenced by patients or actions.
/// </summary>
/// <param name="path">Path where the files is stored</param>
/// <param name="filePrefix">The prefix of the Nhax NHAX file. The file name is "filePrefix-dddddd" where d is digit e.g. "file-000001", "file-000002"</param>
/// <param name="password">Password to access the file</param>
/// <param name="nhaxFileCreatedCallback">Function called when Nhax NHAX file is written. The function is called with the name of the file that is written. Can be set to null.</param>
/// <param name="overwriteExistingFiles">True existing files will be overwritten. If false an error will be reported if file exists.</param>
/// <param name="compressData">If true data are compressed</param>
/// <param name="maxFileSize">Max size of created file. When this size is reached a new Nhax NHAX file is created and data written to this file.</param>
/// <param name="maxPatients">Max patients written to file. When this size is reached new Nhax NHAX file is created and data written to this file.</param>
public NhaxWriter(string path, string filePrefix, string password, NhaxFileCreatedCallback nhaxFileCreatedCallback = null, bool overwriteExistingFiles = false, bool compressData = true, long maxFileSize = ConstMaxFileSize, int maxPatients=ConstMaxPatients)

...

When the NhaxWriter instance has been created WriteUsers and WriteMiscData must be called in order to add users and add Misc data to the Nhax NHAX file. These functions must be called before the WritePatient is called. Each call of WritePatient will add a patient to the Nhax NHAX file.

If using the constructor that takes maxFileSize argument a new Nhax NHAX file is created when the file size exceeds the maxFileSize after a patient is written. When start writing a new Nhax NHAX file the nhaxFileCreatedCallback is called with name of created Nhax NHAX file. The default size of maxFileSize is the advised size when generating Nhax NHAX file that is used when migrating to NoahES.

...

IMPORTANT: Be aware that the Nhax Writer NhaxWriter implements the idisposable interface. It is important that dispose is called in order to update the binary part of the Nhax NHAX file correctly.

Nhax NHAX Reader

The Nhax NHAX reader reads data from an Nhax NHAX file or a stream that contains an Nhax NHAX file. The Nhax NHAX reader can be initialized with file or a stream.

/// <summary>
/// Initializing Nhax NHAX file reader
/// </summary>
/// <param name="password">Password if Nhax NHAX file is encrypted</param>
public ValidateResult Initialize(string filePath, string password)

...

/// <summary>
/// Initializing Nhax NHAX stream reader
/// </summary>
/// <param name="inStream">Stream that contains Nhax NHAX formatted data</param>
/// <param name="password">Password if Nhax NHAX data is encrypted</param>
/// <returns></returns>
public ValidateResult Initialize(Stream inStream, string password)

Be aware that the Nhax NHAX reader implements the idisposable interface. It is important to called the dispose function.

When reading large Nhax NHAX files it is recommended to read a moderate number of patients.

Nhax NHAX Logger Interface

Logging in NhaxLib can be enabled either by implementing the Nhax NHAX logger interface INhaxLogger or create and use the simple logger that NhaxLib implements. The logger must be added using NhaxLogger.AddLogger.

...

Code Block
using Himsa.Noah.NhaxLib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace NhaxFileSplit
{
    internal class NhaxFileSplit
    {
        private static INhaxLogger Logger;

        private static string ExeDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        private static Guid CreatedByGuid = Guid.Parse("08d794ca-012f-4785-9f0d-d0aa42564f1f");
        

        static bool InitLogger()
        {
            // initialise a logger used by Nhax lib
            int logMaxSizeBytes = 10 * 1024 * 1024;

            if (ExeDir == null) {
                Console.WriteLine("Error: failed to get path to executing assembly");
                return false;
            }

            string logPath = Path.Combine(ExeDir, "NhaxFileSplit.log");
            Logger = NhaxLogger.CreateLogger(logPath, true, logMaxSizeBytes);
            NhaxLogger.AddLogger(Logger, NhaxLogLevel.Debug);
            return true;
        }

        static string ToBase64EncodedString(string s)
        {
            if (s == null) return null;
            return Convert.ToBase64String(Encoding.UTF8.GetBytes(s));
        }

        static string FromBase64EncodedString(string s)
        {
            if (s == null) return null;
            byte[] ba = Convert.FromBase64String(s);
            return System.Text.Encoding.UTF8.GetString(ba);
        }


        static bool ValidateResultFailed( ValidateResult vr)
        {
            if (!vr.Validated) return true;
            Console.WriteLine("Error: ValiedateResult {0}", vr.ToString());
            return false;
        }

        static void NhaxFileCallback(string pathToFileCreated)
        {
            Console.WriteLine("Nhax file created: {0}", pathToFileCreated);
        }

        static bool ReadWriteNhaxFile(string inputFile)
        {
            int skip = 0, 
                take = 3;                // Number of patients read in each iteration 
            List<NhaxUser> users;
            List<NhaxPatient> patients;
            int maxFileSize = 1;         // One patient per NhaxNHAX file (size og written a NhaxNHAX file will always be greater than 1)

            string privateDataBase64Encoded = ToBase64EncodedString("Test saving private data");

            using (NhaxWriter writer = new NhaxWriter( ExeDir, "test", null, NhaxFileCallback, true, true, maxFileSize)) {
                using (NhaxReader reader = new NhaxReader()) {
                    if (ValidateResultFailed(reader.Initialize(inputFile, null))) return false;
                    NhaxMiscData miscData = reader.ReadMiscData();
                    if (ValidateResultFailed(reader.ReadUsers(out users))) return false;

                    // Users and misc data must be written before patients is written to NhaxNHAX file
                    if (ValidateResultFailed(writer.WriteMiscData("NhaxFileSplit", CreatedByGuid, privateDataBase64Encoded))) return false;
                    if (ValidateResultFailed(writer.WriteUsers(users))) return false;

                    int noOfPatients = reader.NoOfPatients();
                    while (skip < noOfPatients) {
                        if (skip + take > noOfPatients)
                            take = Math.Min(take, noOfPatients - skip);
                        if (ValidateResultFailed(reader.ReadPatients(skip, take, out patients))) return false;
                        foreach (var patient in patients) {
                            if (ValidateResultFailed(writer.WritePatient(patient))) return false;
                        }
                        skip += take;
                    }
                }
            }

            return true;
        }


        static void Main(string[] args)
        {
            // Program that split an NhaxNHAX file up in a number of NhaxNHAX files each containing one patient
            string inputFile = Path.Combine(ExeDir, "Input.nhax");
            if (args.Length > 0) inputFile = args[0];
            try {
                if (!InitLogger()) return;
                if (!ReadWriteNhaxFile(inputFile)) return;
            }
            catch (Exception e) {
                Console.WriteLine(e);
            }
        }
    }
}

...