/**
         * Find quantity of the specified name, or create it if it is not found.
         *
         * @param quantityName  Name of quantity to find or create. Non-null.
         * @return              Requested quantity. Never null.
         */
        private WitsmlQuantity findOrCreateQuantity(String quantityName,
                                                    String description)
        {
            //Debug.Assert(quantityName != null : "quantityName cannot be null";

            WitsmlQuantity quantity = findQuantity(quantityName);

            if (quantity == null)
            {
                quantity = new WitsmlQuantity(quantityName, description);
                quantities.Add(quantity);
            }

            return(quantity);
        }
        /**
         * Return all units of the specified quantity.
         *
         * @param quantityName  Quantity to get units for. Non-null.
         * @return              All units for the specified quantity. Never null.
         * @throws ArgumentException  If quantityName is null or unknown.
         */
        public List <WitsmlUnit> getUnits(String quantityName)
        {
            if (quantityName == null)
            {
                throw new ArgumentException("quantityName cannot be null");
            }

            WitsmlQuantity quantity = findQuantity(quantityName);

            if (quantity == null)
            {
                throw new ArgumentException("Unknown quantity: " + quantityName);
            }

            return(quantity.getUnits());
        }
        /**
         * Load all quantity and unit information from the local "units.txt" file.
         */
        private void load()
        {
            String fileName = "witsmlUnitDict.xml";
            //String packageName = Assembly.GetExecutingAssembly().GetName().Name;// getClass().getPackage().getName();
            //String packageLocation = packageName.Replace ('.', '/');
            //String filePath = "/" + packageLocation + "/" + fileName;

            // Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(fileName );
            Assembly ass    = this.GetType().Assembly;
            Stream   stream = ass.GetManifestResourceStream(ass.GetName().Name + ".nwitsml.units." + fileName);
            List <WitsmlQuantity> hasBaseUnit = new List <WitsmlQuantity>();


            //InputStream stream = WitsmlUnitManager.class.getResourceAsStream(filePath);

            //SAXBuilder builder = new SAXBuilder();

            try {
                XDocument  document    = XDocument.Load(stream);     // builder.build(stream);
                XElement   rootElement = document.Root;
                XNamespace @namespace  = rootElement.Name.Namespace; //.getNamespace();

                XElement unitDefinitionsElement = rootElement.Element(@namespace + "UnitsDefinition" /*,@namespace*/);
                var      children = unitDefinitionsElement.Elements(@namespace + "UnitOfMeasure" /*, @namespace*/);
                foreach (Object child in children)
                {
                    XElement unitOfMeasureElement = (XElement)child;

                    List <WitsmlQuantity> quantitiesForUnit = new List <WitsmlQuantity>();

                    //
                    // Extract the BaseUnit element with its Description memeber
                    //
                    XElement baseUnitElement = unitOfMeasureElement.Element(@namespace + "BaseUnit" /*, @namespace*/);
                    bool     isBaseUnit      = baseUnitElement != null;

                    String quantityDescription = baseUnitElement != null && baseUnitElement.Element(@namespace + "Description") != null? //bugfix 9-25-10
                                                 baseUnitElement.Element(@namespace + "Description").Value.Trim()
                                                     : null;

                    //
                    // Identify all the quantities this unit appears in
                    //
                    var quantityTypeElements = unitOfMeasureElement.Elements(@namespace + "QuantityType" /*,@namespace*/);
                    foreach (Object child2 in quantityTypeElements)
                    {
                        XElement       quantityTypeElement = (XElement)child2;
                        String         quantityName        = quantityTypeElement.Value.Trim(); //.getTextTrim();
                        WitsmlQuantity quantity            = findOrCreateQuantity(quantityName,
                                                                                  quantityDescription);
                        quantitiesForUnit.Add(quantity);

                        // DEBUG
                        if (isBaseUnit && hasBaseUnit.Contains(quantity))
                        {
                            Console.WriteLine(
                                //System.out.println(
                                "ALREADY BASE: " + quantity.getName());
                        }

                        if (isBaseUnit)
                        {
                            hasBaseUnit.Add(quantity);
                        }
                    }

                    String unitName = unitOfMeasureElement.Element(@namespace + "Name" /*, @namespace*/).Value.Trim();

                    String unitSymbol = unitOfMeasureElement.Element(@namespace + "CatalogSymbol" /*,@namespace*/).Value.Trim();

                    XElement conversionElement = unitOfMeasureElement.Element("ConversionToBaseUnit" /*,@namespace*/);


                    double a = 1.0;
                    double b = 0.0;
                    double c = 0.0;
                    double d = 1.0;

                    if (conversionElement != null)
                    {
                        String   factorText      = conversionElement.Element(@namespace + "Factor" /*,@namespace*/).Value.Trim();
                        XElement fractionElement = conversionElement.Element(@namespace + "Fraction" /*,@namespace*/);
                        XElement formulaElement  = conversionElement.Element(@namespace + "Formula" /*,@namespace*/);

                        if (factorText != null)
                        {
                            try {
                                a = Double.Parse(factorText);
                            }
                            catch (FormatException exception) {
                                //Debug.Assert(false : "Invalid numeric value: " + factorText;
                            }
                        }
                        else if (fractionElement != null)
                        {
                            String numeratorText   = fractionElement.Element(@namespace + "Numerator" /*,@namespace*/).Value.Trim();
                            String denominatorText = fractionElement.Element(@namespace + "Denominator" /*,@namespace*/).Value.Trim();

                            try {
                                double numerator   = Double.Parse(numeratorText);
                                double denominator = Double.Parse(denominatorText);

                                a = numerator / denominator;
                            }
                            catch (FormatException exception) {
                                //Debug.Assert(false : "Invalid numeric value: " + numeratorText + "/" + denominatorText;
                            }
                        }
                        else if (formulaElement != null)
                        {
                            String aText = formulaElement.Element(@namespace + "A" /*, @namespace*/).Value.Trim();
                            String bText = formulaElement.Element(@namespace + "B" /*, @namespace*/).Value.Trim();
                            String cText = formulaElement.Element(@namespace + "C" /*, @namespace*/).Value.Trim();
                            String dText = formulaElement.Element(@namespace + "D" /*, @namespace*/).Value.Trim();

                            try {
                                a = Double.Parse(aText);
                                b = Double.Parse(bText);
                                c = Double.Parse(cText);
                                d = Double.Parse(dText);
                            }
                            catch (FormatException exception) {
                                //Debug.Assert(false : "Invalid numeric value: " + aText + "," + bText + "," + cText + "," + dText;
                            }
                        }
                    }

                    WitsmlUnit unit = new WitsmlUnit(unitName, unitSymbol,
                                                     a, b, c, d);

                    foreach (WitsmlQuantity quantity in quantitiesForUnit)
                    {
                        quantity.addUnit(unit, isBaseUnit);
                    }
                }
            }
            catch (IOException exception) {
                //Debug.Assert(false : "Parse error: " + filePath;
            }
            catch (Exception /*JDOMException*/ exception) {
                //Debug.Assert(false : "Parse error: " + filePath;
            }


            foreach (WitsmlQuantity q in quantities)
            {
                if (!hasBaseUnit.Contains(q))
                {
                    Console.WriteLine(
                        //System.out.println(
                        "NO BASE UNIT: " + q.getName());
                }
            }
        }