LAUREL BRIDGE

LaurelBridge.DCFExamples.CustomUIDGeneration Namespace

DICOM Connectivity Framework V3.4
The CustomUIDGeneration example demonstrates how to use the DCF to customize the generation of UIDs.
Classes

  ClassDescription
Public classProgram
This example demonstrates several approaches on how to generate custom UIDs.
Remarks

Supported OS Platforms:

  • Windows - .Net Framework 4.7.2 64-bit and 32-bit
  • Windows - .Net Core 2.1 64-bit and 32-bit
  • Linux - .Net Core 2.1 64-bit

Examples

CustomUIDGeneration Sample Code
public class Program
{
    /// <summary>
    /// Main entry point for the CustomUIDGeneration example.
    /// </summary>
    public static void Main()
    {
        try
        {
            // Default prefixes, for comparision with examples below
            UidFactory tempFactory = new UidFactory(null, null);
            string defaultOrganizationPrefix = tempFactory.DefaultOrganizationPrefix;
            string defaultSystemPrefix = tempFactory.DefaultSystemPrefix;
            Console.WriteLine("Default org prefix: {0}", defaultOrganizationPrefix);
            Console.WriteLine("Default sys prefix: {0}", defaultSystemPrefix);

            // Example custom prefixes. These would be defined for use by a specific
            // vendor, organization or company, or for a particular desired purpose.
            string customOrganizationPrefix = "1.2.3.4.5.6.7";
            string customSystemPrefix = "9999999999";
            Console.WriteLine("Custom org prefix:  {0}", customOrganizationPrefix);
            Console.WriteLine("Custom sys prefix:  {0}", customSystemPrefix);
            Console.WriteLine();

            // Generate a UID using the default UID factory, for comparison with examples below
            Console.WriteLine("Generated UID (default): {0}", DataDictionary.CreateUid());

            // Generate a UID using the UuidDerivedUidFactory as per the DICOM spec.
            DataDictionary.UidFactory = new UuidDerivedUidFactory();
            Console.WriteLine("UuidDerived UID (with 2.25): {0}", DataDictionary.CreateUid());

            // Generate a UID using the custom organization prefix only
            DataDictionary.UidFactory = new UidFactory(customOrganizationPrefix, null);
            Console.WriteLine("Use org prefix (custom): {0}", DataDictionary.CreateUid());

            // Generate a UID using the custom system prefix only
            DataDictionary.UidFactory = new UidFactory(null, customSystemPrefix);
            Console.WriteLine("Use sys prefix (custom): {0}", DataDictionary.CreateUid());

            // Generate a UID using both custom prefixes only
            DataDictionary.UidFactory = new UidFactory(customOrganizationPrefix, customSystemPrefix);
            Console.WriteLine("sys+org prefix (custom): {0}", DataDictionary.CreateUid());

            // Reset the UID factory and generate using default UID factory
            DataDictionary.UidFactory = null; // assigning null resets it
            Console.WriteLine("Generated UID (default): {0}", DataDictionary.CreateUid());
            Console.WriteLine();

            // Generate N UIDs using default UID factory
            DataDictionary.UidFactory = null;
            const int N = 10;
            for (int i = 0; i < N; i++)
            {
                Console.WriteLine("Generated UID (default) {0}: {1}", i + 1, DataDictionary.CreateUid());
            }
            Console.WriteLine();

            // Generate N UIDs using the UuidDerivedUidFactory
            DataDictionary.UidFactory = new UuidDerivedUidFactory();
            for (int i = 0; i < N; i++)
            {
                Console.WriteLine("Generated UID (from UUID) {0}: {1}", i + 1, DataDictionary.CreateUid());
            }
            Console.WriteLine();

            // Generate N UIDs using custom UID factory
            DataDictionary.UidFactory = new UidFactory(customOrganizationPrefix, customSystemPrefix);
            for (int i = 0; i < N; i++)
            {
                Console.WriteLine("Generated UID (custom) {0}: {1}", i + 1, DataDictionary.CreateUid());
            }
            Console.WriteLine();

            // Generate N UIDs using an extended UID factory
            DataDictionary.UidFactory = new CustomUidFactory(3);
            for (int i = 0; i < N; i++)
            {
                Console.WriteLine("Generated UID (extended) {0}: {1}", i + 1, DataDictionary.CreateUid());
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Error during execution: {0}", e);
            Environment.ExitCode = 1;
        }

        if (Debugger.IsAttached)
        {
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey();
        }
    }

    /// <summary>
    /// This class implements the IUidFactory interface.  The implementation creates a UID from a UUID
    /// according to the description in Chapter 3.5 Appendix B.2 using the root "2.25".
    /// </summary>
    /// <remarks>
    /// <para>
    /// From the specification:
    /// The implementation treats the 128 bit UUID as an integer which may be up to 39 digits long.
    /// Leading zeros must be suppressed.
    /// </para>
    /// <para>
    /// A UUID derived UID may be appropriate for dynamically created UIDs, such as SOP Instance UIDs,
    /// but is usually not appropriate for UIDs determined during application software design, such
    /// as private SOP Class or Transfer Syntax UIDs, or Implementation Class UIDs.
    /// </para>
    /// </remarks>
    internal class UuidDerivedUidFactory : IUidFactory
    {
        public string CreateUid()
        {
            string hexGuid = "0" + Guid.NewGuid().ToString("N");
            BigInteger bigInt = BigInteger.Parse(hexGuid, NumberStyles.HexNumber);
            string uid = String.Format("2.25.{0}", bigInt.ToString("D", CultureInfo.InvariantCulture));
            return uid;
        }

        public bool IsValidUid(string uid)
        {
            return DicomUtils.IsUidValid(uid);
        }
    }

    /// <summary>
    /// You can extend UidFactory and override the protected <see cref="UidFactory.MakeUid">MakeUid</see>
    /// method to use your own algorithm from creating uids.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The following factory assumes you have acquired the organizational prefix 1.2.3.4.5, which is unlikely.
    /// The algorithm used here creates a new guid every 3 iterations and appends a counter value to ensure uniqueness.
    /// Other algorithms might encode the mac address, cpu id, or the date and time, etc.
    /// </para>
    /// <para>
    /// Writing your own algorithm is not to be take lightly.  The uid must start and end with a number, may only
    /// contain the digits 0-9 and periods, and must be 64 characters or less, including the periods.  Multiple periods
    /// in succession are not allowed. Leading 0s in a numeric item are not allowed, unless the item is 0 by itself.
    /// </para>
    /// </remarks>
    internal class CustomUidFactory : UidFactory
    {
        private const string OrgPrefix = "1.2.3.4.5";
        private const int DefaultInterval = 65536;
        private readonly StringBuilder _sb = new StringBuilder();
        private int _counter /*= 0*/;
        private readonly int _interval;

        /// <summary>
        /// Constructor with optional specification of guid reset interval.
        /// </summary>
        /// <param name="interval">How often the guid is reset.</param>
        public CustomUidFactory(int interval = DefaultInterval)
        {
            _interval = interval;
            if (_interval <= 0)
                _interval = DefaultInterval;
        }

        /// <summary>
        /// Override the MakeUid method to do your own thing.  This method is called under lock by <see cref="UidFactory.CreateUid"/>.
        /// The returned uid is validated by the <see cref="UidFactory.IsValidUid"/> method.  This method relies on the
        /// <see cref="Guid.NewGuid"/> to guarantee the uniqueness of the generated UIDs.
        /// </summary>
        /// <returns>A UID string.</returns>
        protected override string MakeUid()
        {
            if (_counter == 0 || _sb.Length == 0)
            {
                string[] items = Guid.NewGuid().ToString("D").Split('-');
                _sb.Length = 0;
                _sb.Append(OrgPrefix);
                foreach (string item in items)
                {
                    _sb.Append(".");
                    _sb.Append(Int64.Parse(item, NumberStyles.AllowHexSpecifier).ToString("D"));
                }
            }
            string result = String.Format("{0}.{1:D}", _sb, _counter + 1);
            _counter = (_counter + 1) % _interval;
            return result;
        }
    }