/// <summary> /// Get the root table associated with a compound id prefix /// </summary> /// <param name="cid"></param> /// <param name="mt"></param> /// <returns></returns> public static MetaTable GetRootMetaTableFromCid( string cid, MetaTable mt) { RootTable rti; MetaTable rootMt; string prefix, suffix, remainder, table; bool dashBeforeNumber, canFormat; int number; if (mt != null) // if metatable is defined see if it is a root table { if (mt.IsRootTable) { return(mt); // if this is a root table then we're done } if (RootTable.IsMultiplePrefixTable(mt)) { return(mt); // if isolated then ignore prefix & use this table } } AnalyzeCid(cid, mt, out prefix, out dashBeforeNumber, out number, out suffix, out remainder, out rti, out rootMt, out canFormat); return(rootMt); }
/// <summary> /// Get the compound id prefix associated with a metatable /// </summary> /// <param name="mt"></param> /// <returns></returns> public static string GetPrefixFromRootTable( MetaTable mt) { string prefix, suffix, table; int number; if (mt == null) { return(""); } mt = mt.Root; // move to root RootTable rti = RootTable.GetFromTableName(mt.Name); if (rti == null) { return(""); } if (Lex.Eq(rti.Prefix, "none") || Lex.Eq(rti.Prefix, "multiple")) { return(""); } else { return(rti.Prefix); } }
/// <summary> /// Get the root table associated with a compound id prefix /// </summary> /// <param name="prefix"></param> /// <param name="rti"></param> /// <param name="mtRoot"></param> public static void GetRootMetaTableFromPrefix( string prefix, out RootTable rti, out MetaTable mtRoot) { rti = null; mtRoot = null; if (prefix == "") { prefix = "none"; // no prefix } if (PrefixToRootTableDict.ContainsKey(prefix)) // already have root info? { rti = PrefixToRootTableDict[prefix]; mtRoot = PrefixToRootMetaTableDict[prefix]; return; } rti = RootTable.GetFromPrefix(prefix); if (rti == null) { return; } string mtName = rti.MetaTableName; mtRoot = MetaTableCollection.Get(mtName); PrefixToRootTableDict[prefix] = rti; PrefixToRootMetaTableDict[prefix] = mtRoot; return; }
/// <summary> /// Return true if in table have multiple prefixes and shouldn't be mixed with other tables /// </summary> /// <param name="mt"></param> /// <returns></returns> public static bool IsMultiplePrefixTable(MetaTable mt) { if (mt == null) { return(false); } RootTable rti = RootTable.GetFromTableName(mt.Root.Name); if (rti == null) { return(false); } return(rti.HasMultiplePrefixes); }
/// <summary> /// Analyze compound id string /// </summary> /// <param name="cid"></param> /// <param name="mt"></param> /// <param name="prefix"></param> /// <param name="dashBeforeNumber"></param> /// <param name="number"></param> /// <param name="suffix"></param> /// <param name="remainder"></param> /// <param name="rti"></param> /// <param name="rootMt"></param> /// <param name="canFormat"></param> public static void AnalyzeCid( string cid, MetaTable mt, out string prefix, out bool dashBeforeNumber, out int number, out string suffix, out string remainder, out RootTable rti, out MetaTable rootMt, out bool canFormat) { // Tests for proper cid conversions // 1. Quick search // 2. Key match, equality // 3. Key match, list editor // 4. Retrieve without structure & check that struct pops up on mouseover of cid // 5. Add structure search for struct model retrieved using key // 6. Run BQ12 to be sure multidatabase search is working (once only) canFormat = true; ParseCid(cid, out prefix, out dashBeforeNumber, out number, out suffix, out remainder); if (prefix == "CorpId") { prefix = ""; // fix for old lists containing CorpId prefix } if (mt != null && mt.IsUserDatabaseStructureTable) // user database structure table { rti = RootTable.GetFromPrefix("USERDATABASE"); rootMt = mt; } else { GetRootMetaTableFromPrefix(prefix, out rti, out rootMt); // normal case } if (RootTable.IsMultiplePrefixTable(mt)) { canFormat = false; // can't format if multiple prefix table } if (rti == null) { canFormat = false; } return; }
/// <summary> /// Filter a set of keys by prefix to match just the supplied root /// </summary> /// <param name="inputKeys"></param> /// <param name="rootTable"></param> /// <returns></returns> public static List <string> FilterKeysByRoot( List <string> inputKeys, MetaTable rootTable) { if (inputKeys == null) { return(inputKeys); } RootTable rti = RootTable.GetFromTableName(rootTable.Name); if (rti == null || !rti.IsStructureTable) { return(inputKeys); // if no structure database associated with root then return keys as is } string prefix = GetPrefixFromRootTable(rootTable); int addCount = 0; foreach (string key in inputKeys) // see how many keys are associated with the current root { if ((prefix == "" && key.Length > 0 && Char.IsDigit(key[0])) || // number with no prefix (prefix != "" & key.StartsWith(prefix)) || // non-blank prefix rti.HasMultiplePrefixes) // single table that stands by itself { addCount++; } } if (addCount == inputKeys.Count) { return(inputKeys); // no change } List <string> keys = new List <string>(); // need to build subset of keys foreach (string key in inputKeys) { if ((prefix == "" && key.Length > 0 && Char.IsDigit(key[0])) || // number with no prefix (prefix != "" & key.StartsWith(prefix)) || // non-blank prefix rti.HasMultiplePrefixes) // single table that stands by itself { keys.Add(key); } } return(keys); }
/// <summary> /// Try to get root table from table name, label and SmallWorld db name in order /// </summary> /// <param name="tableId"></param> /// <returns></returns> public static RootTable GetFromTableId( string tableId) { RootTable rt = GetFromTableName(tableId); if (rt == null) { rt = GetFromTableLabel(tableId); } if (rt == null) { rt = GetFromSwName(tableId); } return(rt); }
/// <summary> /// Normalize from int value (fast) /// </summary> /// <param name="cid"></param> /// <param name="mt"></param> /// <returns></returns> public static string Normalize( int intCid, MetaTable mt) { RootTable rt; string fmt; if (mt == null) { return(intCid.ToString()); } if (mt.Root == LastNormalizeRootMetaTable) { // same as last time? rt = LastNormalizeRootTable; fmt = LastNormalizeFmt; } else { MetaTable mtRoot = mt.Root; rt = RootTable.GetFromTableName(mtRoot.Name); if (rt == null) { return(intCid.ToString()); } fmt = "{0," + rt.InternalNumberFormat + "}"; LastNormalizeRootMetaTable = mtRoot; LastNormalizeRootTable = rt; LastNormalizeFmt = fmt; } string cidString = String.Format(fmt, intCid); if (rt.HasSinglePrefix) { cidString = rt.Prefix + cidString; } return(cidString); }
/// <summary> /// Get a dictionary /// </summary> /// <param name="dictName"></param> /// <returns></returns> public static DictionaryMx GetWithException( // lookup or read dictionary and return string dictName) { string sql, tok; //if (Lex.Eq(dictName, "DIT_PERSON")) dictName = dictName; // debug if (dictName == null || dictName == "") { throw new Exception("Dictionary name not defined"); } if (RootTable.IsDatabaseListDictionaryName(dictName)) { // dict of root tables move to factory after Mobius 2.4 is deactivated return(RootTable.GetDictionary(dictName)); } dictName = dictName.ToLower(); DictionaryMx dict = Dictionaries[dictName]; if (dict == null) { throw new Exception("Dictionary not defined: " + dictName); } if (dict.Words == null) { if (DictionaryFactory == null) { throw new Exception("DictionaryFactory not defined"); } int t0 = TimeOfDay.Milliseconds(); DictionaryFactory.GetDefinitions(dict); t0 = TimeOfDay.Milliseconds() - t0; //DebugLog.Message("DictionaryMx.Get " + dictName + ", time: " + t0); } return(dict); }
/// <summary> /// Add dash to prefix if appropriate /// May be because the prefix normally has a dash or because of negative cid value /// </summary> /// <param name="prefix"></param> /// <param name="dashBeforeNumber"></param> /// <param name="rti"></param> static void AddDashIfAppropriate( ref string prefix, bool dashBeforeNumber, RootTable rti) { if (prefix.EndsWith("-")) { return; } if (rti == null) { return; } if ((prefix != "" && rti.Prefix.EndsWith("-")) || // if we have a prefix & the prefix for this table ends with a dash (dashBeforeNumber && rti.NegativeNumberAllowed)) // or there's a dash & negative cids are allowed { prefix += "-"; } return; }
/// <summary> /// Return true if the specified table is the root of a structure database /// </summary> /// <param name="mtName"></param> /// <returns></returns> public static bool IsStructureDatabaseRootTable(string tableName) { if (TableList == null) { Build(); } tableName = tableName.Trim().ToLower(); if (TableDictionary.ContainsKey(tableName)) { RootTable root = TableDictionary[tableName]; return(root.IsStructureTable); } else if (Mobius.Data.MetaTable.IsUserDatabaseStructureTableName(tableName)) { return(true); } else { return(false); } }
public static void Deserialize(XmlTextReader tr) { TableList = new List <RootTable>(); TableDictionary = new Dictionary <string, RootTable>(); PrefixDictionary = new Dictionary <string, RootTable>(); LabelDictionary = new Dictionary <string, RootTable>(); if (tr.ReadState == ReadState.Initial) // read first element if not done yet { tr.Read(); tr.MoveToContent(); } if (Lex.Eq(tr.Name, "RootTables")) // multiple metatables { tr.Read(); // move to first MetaTable tr.MoveToContent(); } while (true) // loop on tables { if (tr.NodeType == XmlNodeType.Element && Lex.Eq(tr.Name, "RootTable")) { RootTable i = new RootTable(); XmlUtil.GetStringAttribute(tr, "Label", ref i.Label); XmlUtil.GetIntAttribute(tr, "DbId", ref i.DatabaseId); //if (Lex.Eq(i.Label, "lida")) i = i; // debug XmlUtil.GetStringAttribute(tr, "MetaTable", ref i.MetaTableName); XmlUtil.GetBoolAttribute(tr, "IsStructureTable", ref i.IsStructureTable); if (!i.IsStructureTable) // if not a structure table can't do any structure searches on the table { i.CartridgeSearchable = false; } XmlUtil.GetBoolAttribute(tr, "CartridgeSearchable", ref i.CartridgeSearchable); XmlUtil.GetBoolAttribute(tr, "EcfpSearchable", ref i.EcfpSearchable); XmlUtil.GetStringAttribute(tr, "SmallWorldDbName", ref i.SmallWorldDbName); XmlUtil.GetStringAttribute(tr, "CidUrl", ref i.CidUrl); XmlUtil.GetStringAttribute(tr, "Prefix", ref i.Prefix); XmlUtil.GetBoolAttribute(tr, "PrefixIsStored", ref i.PrefixIsStored); XmlUtil.GetBoolAttribute(tr, "IsStringType", ref i.IsStringType); XmlUtil.GetBoolAttribute(tr, "NegativeNumberAllowed", ref i.NegativeNumberAllowed); XmlUtil.GetStringAttribute(tr, "InternalFormat", ref i.InternalNumberFormat); XmlUtil.GetStringAttribute(tr, "ExternalFormat", ref i.ExternalNumberFormat); if (i.IsStructureTable && !i.HasMultiplePrefixes) { // include prefixes for structure tables only if (i.Prefix == "") { i.Prefix = "none"; // non-blank value for lookup } PrefixDictionary[i.Prefix.ToLower()] = i; } TableList.Add(i); LabelDictionary[i.Label.ToLower()] = i; TableDictionary[i.MetaTableName.ToLower()] = i; //SetSimSearchability(); if (tr.IsEmptyElement) // is this an empty element? { tr.Read(); // move to next element tr.MoveToContent(); continue; } tr.Read(); // move to next element tr.MoveToContent(); if (Lex.Eq(tr.Name, "RootTable") && tr.NodeType == XmlNodeType.EndElement) { } else { throw new Exception("Expected RootTable EndElement"); } tr.Read(); // move to next element tr.MoveToContent(); } else { if (Lex.Eq(tr.Name, "RootTables") && tr.NodeType == XmlNodeType.EndElement) { } else { throw new Exception("Expected RootTables EndElement"); } return; } } }
/// <summary> /// Convert a compound number from internal to external format /// </summary> /// <param name="cid"></param> /// <param name="mt"></param> /// <returns></returns> public static string Format( string normalizedCid, MetaTable mt) { string prefix = "", suffix = "", remainder = "", nTxt, fmt, fCid; bool dashBeforeNumber, canFormat; RootTable rti = null, rtiBase; MetaTable rootMt; int number = -1; //if (mt == null) mt = mt; // debug string cid = normalizedCid; if (String.IsNullOrEmpty(cid)) { return(cid); } if (mt != null && !RootTable.IsStructureDatabaseRootTable(mt.Root)) // non structure root table { if (mt.Root.KeyMetaColumn.IsNumeric && Lex.IsInteger(cid)) { // if numeric then return as simple integer with leading zeros removed number = int.Parse(cid); fCid = number.ToString(); return(fCid); } else { return(cid); // just return as is } } cid = Lex.RemoveAllQuotes(cid.Trim()).Trim(); // clean up if (cid.Length == 0) { return(""); // something really there } if (mt != null && UserObject.IsUserDatabaseStructureTableName(mt.Root.Name)) { // user database if (Lex.IsInteger(cid)) // if number format with no leading zeros { return(Int32.Parse(cid).ToString()); } else { return(cid); // otherwise return as is } } if (RootTable.IsMultiplePrefixTable(mt)) { return(cid); // no formatting just return as is } AnalyzeCid(cid, mt, out prefix, out dashBeforeNumber, out number, out suffix, out remainder, out rti, out rootMt, out canFormat); if (!canFormat) { return(cid); } if (prefix == "") { prefix = "none"; } rti = RootTable.GetFromPrefix(prefix); if (rti == null || Lex.IsNullOrEmpty(rti.ExternalNumberFormat)) { fmt = "{0}"; // unknown prefix } else { fmt = "{0," + rti.ExternalNumberFormat + "}"; } if (prefix == "none") { prefix = ""; } if (number < 0) { nTxt = ""; } else { try { nTxt = String.Format(fmt, number); } catch (Exception ex) { nTxt = number.ToString(); } } AddDashIfAppropriate(ref prefix, dashBeforeNumber, rti); fCid = prefix + nTxt + suffix; if (fCid == "") { return(cid); } return(fCid); }
/// <summary> /// Normalize compound number for database searching/storage /// </summary> /// <param name="cid"></param> /// <param name="mt"></param> /// <returns></returns> public static string NormalizeForDatabase( string unnormalizedCid, MetaTable mt) { RootTable rti = null; MetaTable rootMt; string cid, prefix = "", suffix = "", remainder = "", nTxt = "", fmt, nCid; bool dashBeforeNumber = false, canFormat; int number = -1; // if (cid.Contains("91341")) cid = cid; // debug // if (mt == null) mt = mt; // debug cid = NormalizeCase(unnormalizedCid, mt); if (String.IsNullOrEmpty(cid)) { return(cid); } if (cid.Contains(" ")) { cid = cid.Replace(" ", "_"); // replace any spaces with underscores } if (cid.Contains("\n")) { cid = cid.Replace("\n", ""); // remove newlines } if (cid.Contains("\r")) { cid = cid.Replace("\r", ""); // remove returns } if (mt != null && !RootTable.IsStructureDatabaseRootTable(mt.Root)) { return(cid); } if (RootTable.IsMultiplePrefixTable(mt)) { return(cid); // no formatting just return as is } if (mt != null && UserObject.IsUserDatabaseStructureTableName(mt.Root.Name)) { // user database prefix = "userdatabase"; // used to lookup format if (Lex.IsInteger(cid)) { number = Int32.Parse(cid); } else { suffix = cid; } } else // other database { if (mt != null && RootTable.GetFromTableName(mt.Root.Name) == null) { return(cid); // if not a recognized database return cid as is } AnalyzeCid(cid, mt, out prefix, out dashBeforeNumber, out number, out suffix, out remainder, out rti, out rootMt, out canFormat); if (!canFormat) { return(cid); } string mtPrefix = ""; if (mt != null) // get any prefix for metatable { mtPrefix = GetPrefixFromRootTable(mt); } if (mtPrefix.EndsWith("-") && prefix != "" && !prefix.EndsWith("-")) { // adjust to allow prefix match prefix += "-"; dashBeforeNumber = false; } if (prefix == "") // if no prefix in number then add any metatable prefix { if (mtPrefix != "") { prefix = mtPrefix; } else { prefix = "none"; } } else if (mt != null && !Lex.Eq(prefix, mtPrefix)) { return(null); // if prefix invalid for database return null } } rti = RootTable.GetFromPrefix(prefix); if (rti == null && prefix == "userdatabase") { fmt = "{0,8:00000000}"; // default format for user databases prefix = ""; } else if (rti == null || Lex.IsNullOrEmpty(rti.InternalNumberFormat)) { // unknown format fmt = "{0}"; // default format if (rti != null && !rti.PrefixIsStored) { prefix = ""; // database doesn't contain prefix } } else // use supplied format { fmt = "{0," + rti.InternalNumberFormat + "}"; if (!rti.PrefixIsStored) { prefix = ""; // database doesn't contain prefix } } if (number < 0) { nTxt = ""; } else { try { nTxt = String.Format(fmt, number); } catch (Exception ex) { nTxt = number.ToString(); } } //if (Lex.StartsWith(cid, "GGO-")) nTxt = "-" + nTxt; // hack for GeneGo database, fix later if (prefix == "none") { prefix = ""; } AddDashIfAppropriate(ref prefix, dashBeforeNumber, rti); nCid = (prefix + nTxt + suffix).ToUpper(); if (nCid.Contains(" ")) { nCid = nCid.Replace(" ", "_"); // replace any internal spaces with underscores } return(nCid); }
/// <summary> /// Convert a compound number from external to internal format /// normalizing and adding a prefix as needed. /// A false prefix is added for compound collections that don't normally include /// a prefix or contain a overlapping prefix to keep compoundIds associated /// with the proper compound collection. /// This routine handles several cases: /// 1 - If mt defined & root is not a compound table then just return key as is /// 2 - If mt defined & root is a UCDB then normalize to fixed length if numeric otherwise return as is /// 3 - If mt defined & compound table root & no prefix then get any default prefix /// 4 - If string cid value then add any prefix & return as is /// 5 - if numeric cid (stored as integer or string) then add any prefix & format numeric part /// </summary> /// <param name="cid"></param> /// <param name="mt"></param> /// <returns></returns> public static string Normalize( string unnormalizedCid, MetaTable mt) { RootTable rti = null; MetaTable rootMt; string prefix = "", suffix = "", remainder = "", nTxt = "", fmt, nCid; bool dashBeforeNumber, canFormat; int number = -1; if (mt == null) { mt = mt; // debug } string cid = NormalizeCase(unnormalizedCid, mt); if (String.IsNullOrEmpty(cid)) { return(cid); } if (cid.IndexOf(",") >= 0) // if comma in list then just use chars up to comma { cid = cid.Substring(0, cid.IndexOf(",")); } AnalyzeCid(cid, mt, out prefix, out dashBeforeNumber, out number, out suffix, out remainder, out rti, out rootMt, out canFormat); if (!canFormat) { return(cid); } //if (!CanFormat(cid, prefix //if (!String.IsNullOrEmpty(remainder)) // multiple tokens, just return as is // return cid; // (for a cid like "2." the wrong value is returned, i.e. 2. // if (Lex.Eq(prefix, "MDDR") && number == 91341) prefix = prefix; // debug if (mt != null) // know the metatable this should belong to { // note: for multi-root table search the root table may not correspond to the compoundId prefix & value if (!RootTable.IsStructureDatabaseRootTable(mt.Root)) // non structure root table? { if (mt.Root.KeyMetaColumn.IsNumeric && Lex.IsInteger(cid)) { // if numeric then default internal format is length 10 with leading zeros number = int.Parse(cid); nCid = string.Format("{0:0000000000}", number); return(nCid); } else { return(cid); // just return as is } } else if (UserObject.IsUserDatabaseStructureTableName(mt.Root.Name)) { return(NormalizeForDatabase(cid, mt)); // same as for database if user database } else // Normal case, non-userDatabase structure root table { rti = RootTable.GetFromTableName(mt.Root.Name); if (prefix == "") { prefix = GetPrefixFromRootTable(mt); } if (rti != null && rti.IsStringType && String.IsNullOrEmpty(rti.InternalNumberFormat)) { // general unformatted string, just add any required prefix & return if (!String.IsNullOrEmpty(rti.Prefix) && !Lex.StartsWith(cid, rti.Prefix)) { nCid = rti.Prefix + cid; // add prefix if needed } else { nCid = cid; // just return as is } return(nCid); } } } else // metatable not defined, try to determine from prefix { if (!String.IsNullOrEmpty(prefix)) { rti = RootTable.GetFromPrefix(prefix); } else if (Lex.IsInteger(cid)) // if integer cid then use default integer cid database { rti = RootTable.GetFromPrefix(""); } } if (rti == null || Lex.IsNullOrEmpty(rti.InternalNumberFormat)) { fmt = "{0}"; // unknown prefix } else { fmt = "{0," + rti.InternalNumberFormat + "}"; } if (prefix == "") { suffix = ""; // if no prefix, disallow suffix to avoid invalid numbers for numeric keys (possibly enhance later) } if (number < 0) { nTxt = ""; // no number } else { try { nTxt = String.Format(fmt, number); } catch (Exception ex) { nTxt = number.ToString(); } } AddDashIfAppropriate(ref prefix, dashBeforeNumber, rti); nCid = prefix + nTxt + suffix; if (nCid == "") { nCid = cid.Trim(); // if nothing then return original input } return(nCid); }