/// <summary> /// Compose UOM from signature which is not defined in source definition file. Find master UOMs, calculate scale, generate label. The signature could be of any complexity. /// </summary> /// <param name="ANewSignature">A new signature</param> /// <returns>Newly composed UOM. Please, note, the new UOM signature could differ on source signature.</returns> protected UOM Compose(string ANewSignature) { #if DEBUG CheckSignature(ANewSignature); #endif Atom[] atoms = Atomize(ANewSignature); // Search for master UOMs UOM[] masters = new UOM[atoms.Length]; UOM newUOM = new UOM(); newUOM.Scale = 1.0; newUOM.Signature = ANewSignature; for (int ct = 0; ct < atoms.Length; ct++) { Atom atom = atoms[ct]; if (!UOMs.ContainsKey(atom.AtomicUOM + "1")) { throw new Exception("UnitMan failed to compose new UOM for signature " + ANewSignature + ". Atomic UOM " + atom.AtomicUOM + " not found."); } // Atomic UOM found in list. Check if it is master and update scale of new UOM if not. UOM src = UOMs[atom.AtomicUOM + "1"].Clone(); if (src.IsMaster) { masters[ct] = src; } else { UOM master = src.Master; // Update scale of new UOM for (int cte = 0; cte < Atom.Abs(atom.Exponent); cte++) { newUOM.Scale *= atom.Exponent > 0 ? src.Scale : 1.0 / src.Scale; } masters[ct] = master.Clone(); } } // Masters are of positive exponents here. The exponents could be large than 1. for (int ct = 0; ct < masters.Length; ct++) { masters[ct].Signature = masters[ct].Signature.Replace("1", Atom.Abs(atoms[ct].Exponent).ToString()); // That's why I need clone master UOM's } // Create the master signature string masterSignature = masters[0].Signature; for (int ct = 1; ct < masters.Length; ct++) { masterSignature += masters[ct].Signature; } Atom[] masterAtoms = Atomize(masterSignature); for (int ct = 0; ct < masterAtoms.Length; ct++) { if (atoms[ct].Exponent < 0) { masterAtoms[ct].Neg(); // Restore signs } } Array.Sort(masterAtoms); masterSignature = Recombine(masterAtoms); // Check the master and domain exists if (!UOMs.ContainsKey(masterSignature)) { throw new Exception("Domain for UOM " + ANewSignature + " not found"); } UOM masterUOM = UOMs[masterSignature]; // Generate label bool slash = false; newUOM.Label = ""; for (int ct = 0; ct < atoms.Length; ct++) { // check the slash shall be inserted if (!slash && atoms[ct].Exponent < 0) { if (ct == 0) { newUOM.Label = "1/"; } else { newUOM.Label += "/"; } slash = true; } newUOM.Label += atoms[ct].AtomicUOM; if (Math.Abs(atoms[ct].Exponent) > 1) { newUOM.Label += (int)Math.Abs(atoms[ct].Exponent); } } newUOM.Name = newUOM.Label; newUOM.Plural = newUOM.Label; newUOM.Master = masterUOM; UOMs.Add(newUOM.Signature, newUOM); return(newUOM); }