)>}]
شركة التطبيقات المتكاملة لتصميم وبرمجة البرمجيات الخاصة ش.ش.و.
Integrated Applications Programming Company
Home » Code Library » Ims (Ia.Ftn.Cl.Models.Business.Nokia)

Public general use code classes and xml files that we've compiled and used over the years:

Fixed Telecommunications Network's Operations Support System Management Intranet (FTN OSS) support class for Nokia's Fixed Telecommunications Network (FTN) business model.

    1: using Microsoft.EntityFrameworkCore;
    2: using System;
    3: using System.Collections.Generic;
    4: using System.Configuration;
    5: using System.Data;
    6: using System.Linq;
    7:  
    8: namespace Ia.Ftn.Cl.Models.Business.Nokia
    9: {
   10:     ////////////////////////////////////////////////////////////////////////////
   11:  
   12:     /// <summary publish="true">
   13:     /// Fixed Telecommunications Network's Operations Support System Management Intranet (FTN OSS) support class for Nokia's Fixed Telecommunications Network (FTN) business model.
   14:     /// </summary>
   15:     /// 
   16:     /// <value>
   17:     ///   <appSettings>
   18:     ///     <add key="imsServerHost" value="https://*" />
   19:     ///     <add key="imsServerPort" value="*" />
   20:     ///     <add key="imsServerServiceUrl" value="*" />
   21:     ///     <add key="imsServerUser" value="*" />
   22:     ///     <add key="imsServerUserPassword" value="*" />
   23:     ///   </appSettings>
   24:     /// </value>
   25:     /// 
   26:     /// <remarks> 
   27:     /// Copyright © 2014-2021 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
   28:     /// </remarks> 
   29:     public class Ims
   30:     {
   31:         // below: this is the almost official GwId range used
   32:  
   33:         private const int gwIdFirst = 2048;
   34:         private const int gwIdLast = 65535;
   35:  
   36:         private const int primaryPUIDCPEProfileNumberForSip = 10;
   37:         private const int primaryPUIDCPEProfileNumberForH248 = 35;
   38:  
   39:         private const string sipSubscriberRegistrationPassword = "1234"; // as per Nokia spec
   40:  
   41:         private static List<int> allPossibleGwIdList = new List<int>();
   42:         private static List<int> allPossibleServiceNumberList = new List<int>();
   43:         private static Queue<string> agcfEndpointPrividUserQueue = new Queue<string>();
   44:  
   45:         private static Ia.Ftn.Cl.Models.Business.Procedure procedureNokiaImsSubscriberToBeUpdatedFromH248ToSipList = new Ia.Ftn.Cl.Models.Business.Procedure(Ia.Ftn.Cl.Models.Business.Provision.NokiaImsSubscriberToBeUpdatedFromH248ToSipList);
   46:  
   47:         /// <summary/>
   48:         public class ImsBasicService
   49:         {
   50:             public string MgcIp;
   51:             public string MgcSecondaryIp;
   52:             public string MgcSubnetMask;
   53:             public int Service;
   54:             public string Fsdb;
   55:             public string PrimarySwitch;
   56:         }
   57:  
   58:         /// <summary/>
   59:         public static ImsBasicService[] ImsBasicServiceList =
   60:             {
   61:             new ImsBasicService { MgcIp="10.16.1.31", MgcSecondaryIp="10.16.5.31", MgcSubnetMask="255.255.224.0",Service=0,Fsdb="fsdb0",PrimarySwitch=TEC },
   62:             new ImsBasicService { MgcIp="10.16.1.32", MgcSecondaryIp="10.16.5.32", MgcSubnetMask="255.255.224.0",Service=1,Fsdb="fsdb1",PrimarySwitch=TEC },
   63:             new ImsBasicService { MgcIp="10.16.1.33", MgcSecondaryIp="10.16.5.33", MgcSubnetMask="255.255.224.0",Service=2,Fsdb="fsdb1",PrimarySwitch=TEC },
   64:             new ImsBasicService { MgcIp="10.16.1.34", MgcSecondaryIp="10.16.5.34", MgcSubnetMask="255.255.224.0",Service=3,Fsdb="fsdb1",PrimarySwitch=TEC },
   65:             new ImsBasicService { MgcIp="10.16.1.35", MgcSecondaryIp="10.16.5.35", MgcSubnetMask="255.255.224.0",Service=4,Fsdb="fsdb2",PrimarySwitch=TEC },
   66:             new ImsBasicService { MgcIp="10.16.1.36", MgcSecondaryIp="10.16.5.36", MgcSubnetMask="255.255.224.0",Service=5,Fsdb="fsdb2",PrimarySwitch=TEC },
   67:             new ImsBasicService { MgcIp="10.16.1.37", MgcSecondaryIp="10.16.5.37", MgcSubnetMask="255.255.224.0",Service=6,Fsdb="fsdb2",PrimarySwitch=TEC },
   68:             new ImsBasicService { MgcIp="10.16.1.38", MgcSecondaryIp="10.16.5.38", MgcSubnetMask="255.255.224.0",Service=7,Fsdb="fsdb3",PrimarySwitch=TEC },
   69:             new ImsBasicService { MgcIp="10.16.1.39", MgcSecondaryIp="10.16.5.39", MgcSubnetMask="255.255.224.0",Service=8,Fsdb="fsdb3",PrimarySwitch=TEC },
   70:             new ImsBasicService { MgcIp="10.16.1.40", MgcSecondaryIp="10.16.5.40", MgcSubnetMask="255.255.224.0",Service=9,Fsdb="fsdb3",PrimarySwitch=TEC },
   71:  
   72:             new ImsBasicService { MgcIp="10.16.5.31", MgcSecondaryIp="10.16.1.31", MgcSubnetMask="255.255.224.0",Service=0,Fsdb="fsdb0",PrimarySwitch=SKB },
   73:             new ImsBasicService { MgcIp="10.16.5.32", MgcSecondaryIp="10.16.1.32", MgcSubnetMask="255.255.224.0",Service=1,Fsdb="fsdb1",PrimarySwitch=SKB },
   74:             new ImsBasicService { MgcIp="10.16.5.33", MgcSecondaryIp="10.16.1.33", MgcSubnetMask="255.255.224.0",Service=2,Fsdb="fsdb1",PrimarySwitch=SKB },
   75:             new ImsBasicService { MgcIp="10.16.5.34", MgcSecondaryIp="10.16.1.34", MgcSubnetMask="255.255.224.0",Service=3,Fsdb="fsdb1",PrimarySwitch=SKB },
   76:             new ImsBasicService { MgcIp="10.16.5.35", MgcSecondaryIp="10.16.1.35", MgcSubnetMask="255.255.224.0",Service=4,Fsdb="fsdb2",PrimarySwitch=SKB },
   77:             new ImsBasicService { MgcIp="10.16.5.36", MgcSecondaryIp="10.16.1.36", MgcSubnetMask="255.255.224.0",Service=5,Fsdb="fsdb2",PrimarySwitch=SKB },
   78:             new ImsBasicService { MgcIp="10.16.5.37", MgcSecondaryIp="10.16.1.37", MgcSubnetMask="255.255.224.0",Service=6,Fsdb="fsdb2",PrimarySwitch=SKB },
   79:             new ImsBasicService { MgcIp="10.16.5.38", MgcSecondaryIp="10.16.1.38", MgcSubnetMask="255.255.224.0",Service=7,Fsdb="fsdb3",PrimarySwitch=SKB },
   80:             new ImsBasicService { MgcIp="10.16.5.39", MgcSecondaryIp="10.16.1.39", MgcSubnetMask="255.255.224.0",Service=8,Fsdb="fsdb3",PrimarySwitch=SKB },
   81:             new ImsBasicService { MgcIp="10.16.5.40", MgcSecondaryIp="10.16.1.40", MgcSubnetMask="255.255.224.0",Service=9,Fsdb="fsdb3",PrimarySwitch=SKB },
   82:         };
   83:  
   84:         /// <summary/>
   85:         public static int FirstGatewayId { get { return gwIdFirst; } }
   86:  
   87:         /// <summary/>
   88:         public static int LastGatewayId { get { return gwIdLast; } }
   89:  
   90:         /// <summary/>
   91:         public static string BaseAddress { get { return Ia.Cl.Models.ApplicationConfiguration.GetSetting("AppSettings:ImsServerHost") + ":" + Ia.Cl.Models.ApplicationConfiguration.GetSetting("AppSettings:ImsServerPort"); } }
   92:  
   93:         /// <summary/>
   94:         public static string ServiceUrl { get { return Ia.Cl.Models.ApplicationConfiguration.GetSetting("AppSettings:ImsServerServiceUrl"); } }
   95:  
   96:         /// <summary/>
   97:         public static string UserName { get { return Ia.Cl.Models.ApplicationConfiguration.GetSetting("AppSettings:ImsServerUser"); } }
   98:  
   99:         /// <summary/>
  100:         public static string Password { get { return Ia.Cl.Models.ApplicationConfiguration.GetSetting("AppSettings:ImsServerUserPassword"); } }
  101:  
  102:         /// <summary/>
  103:         public static string AnyPrimarySwitch { get { return TEC; } }
  104:  
  105:         /// <summary/>
  106:         public static string TEC { get { return "TECICS01"; } }
  107:  
  108:         /// <summary/>
  109:         public static string SKB { get { return "SKBICS02"; } }
  110:  
  111:  
  112:         /// <summary/>
  113:         public const int MaximumCombinedNumberOfAgcfGatewayRecordsInAnyMgcIpAndMgcSecondaryIpPair = 4800; // limit defind by Nokia
  114:  
  115:         /// <summary/>
  116:         public static int PrimaryPUIDCPEProfileNumberForSip { get { return primaryPUIDCPEProfileNumberForSip; } }
  117:  
  118:         /// <summary/>
  119:         public static int PrimaryPUIDCPEProfileNumberForH248 { get { return primaryPUIDCPEProfileNumberForH248; } }
  120:  
  121:         /// <summary/>
  122:         public static string SipSubscriberRegistrationPassword { get { return sipSubscriberRegistrationPassword; } }
  123:  
  124:         /// <summary/>
  125:         public static List<string> FsdbList = new List<string> { "fsdb0", "fsdb1", "fsdb2", "fsdb3" };
  126:  
  127:         /// <summary/>
  128:         public static List<int> NokiaImsPrefixesAsPerNokia2021 = new List<int> { 1810407, 1830011, 22239, 2323, 2324, 2360, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2374, 2380, 2435, 2436, 2438, 2453, 2454, 2460, 2461, 2464, 2465, 2466, 2468, 2469, 24780, 24781, 24782, 2490, 2493, 24973, 24974, 24975, 24976, 24977, 24978, 24979, 2520, 2521, 2522, 2523, 2524, 2529, };
  129:  
  130:         ////////////////////////////////////////////////////////////////////////////
  131:  
  132:         /// <summary>
  133:         /// Response of IMS
  134:         /// </summary>
  135:         public class Response
  136:         {
  137:             /// <summary/>
  138:             public int Service { get; set; }
  139:  
  140:             /// <summary/>
  141:             public bool IsSuccess { get { return ResultCode == Ia.Ftn.Cl.Models.Client.Nokia.Ims.ResultCode.Successful; } }
  142:  
  143:             /// <summary/>
  144:             public bool IsProvisioned { get; set; }
  145:  
  146:             /// <summary/>
  147:             public Ia.Ftn.Cl.Models.Client.Nokia.Ims.ResultCode ResultCode { get; set; }
  148:  
  149:             /// <summary/>
  150:             //public string Ctag { get; set; } // no need because the commad string is included in response body
  151:  
  152:             /// <summary/>
  153:             public DateTime DateTime { get; set; }
  154:  
  155:             /// <summary/>
  156:             public string CommandString { get; set; }
  157:  
  158:             /// <summary/>
  159:             public string FailureReason { get; set; }
  160:  
  161:             /// <summary/>
  162:             public string FailureCode { get; set; }
  163:  
  164:             /// <summary/>
  165:             //public Dictionary<string, string> ParameterDictionary { get; set; }
  166:  
  167:             /// <summary/>
  168:             public List<Dictionary<string, string>> ParameterDictionaryList { get; set; }
  169:  
  170:             /// <summary/>
  171:             public Response() { }
  172:         }
  173:  
  174:         ////////////////////////////////////////////////////////////////////////////
  175:  
  176:         /// <summary>
  177:         ///
  178:         /// </summary>
  179:         public Ims()
  180:         {
  181:         }
  182:  
  183:         ////////////////////////////////////////////////////////////////////////////
  184:  
  185:         /// <summary>
  186:         /// 
  187:         /// </summary>
  188:         public static List<string> NumberOfNokiaH248SubsribersPerFsdb()
  189:         {
  190:             string imsFsdb;
  191:             Dictionary<string, string> ontListNokiaIpToPrimarySwitchImsFsdbDictionary;
  192:             List<string> list;
  193:  
  194:             var dictionary = new Dictionary<string, int>();
  195:  
  196:             ontListNokiaIpToPrimarySwitchImsFsdbDictionary = Ia.Ftn.Cl.Models.Data.NetworkDesignDocument.NokiaOntIpToPrimarySwitchImsFsdbDictionary;
  197:  
  198:             using (var db = new Ia.Ftn.Cl.Db())
  199:             {
  200:                 list = (from e in db.AgcfEndpoints
  201:                         join gr in db.AgcfGatewayRecords on e.AgcfGatewayRecord.Id equals gr.Id
  202:                         select gr.IP1).AsNoTracking().ToList();
  203:             }
  204:  
  205:             foreach (string ip in list)
  206:             {
  207:                 if (ontListNokiaIpToPrimarySwitchImsFsdbDictionary.ContainsKey(ip))
  208:                 {
  209:                     imsFsdb = ontListNokiaIpToPrimarySwitchImsFsdbDictionary[ip];
  210:  
  211:                     if (dictionary.ContainsKey(imsFsdb)) dictionary[imsFsdb]++;
  212:                     else dictionary[imsFsdb] = 1;
  213:                 }
  214:             }
  215:  
  216:             list.Clear();
  217:  
  218:             foreach (KeyValuePair<string, int> kvp in dictionary)
  219:             {
  220:                 list.Add(kvp.Key + ": " + kvp.Value);
  221:             }
  222:  
  223:             return list;
  224:         }
  225:  
  226:         ////////////////////////////////////////////////////////////////////////////
  227:  
  228:         /// <summary>
  229:         /// 
  230:         /// </summary>
  231:         public static List<string> NumberOfNokiaSipSubsribersPerFsdb()
  232:         {
  233:             string imsFsdb;
  234:             Dictionary<string, string> ontListNokiaIpToPrimarySwitchImsFsdbDictionary;
  235:  
  236:             var list = new List<string>();
  237:  
  238:             var dictionary = new Dictionary<string, int>();
  239:  
  240:             ontListNokiaIpToPrimarySwitchImsFsdbDictionary = Ia.Ftn.Cl.Models.Data.NetworkDesignDocument.OntIpToPrimarySwitchImsFsdbDictionary;
  241:  
  242:             using (var db = new Ia.Ftn.Cl.Db())
  243:             {
  244:                 var list0 = (from s in db.Subscribers
  245:                              join sp in db.SubParties on s.SubParty.Id equals sp.Id
  246:                              join eosi in db.EmsOntSipInfoes on s.PartyId equals eosi.SIPUSERNAME
  247:                              join eo in db.EmsOnts on eosi.EmsOnt.Id equals eo.Id
  248:                              select eo.Id).AsNoTracking().ToList();
  249:  
  250:                 var list1 = (from s in db.Subscribers
  251:                              join sp in db.SubParties on s.SubParty.Id equals sp.Id
  252:                              join evpu in db.EmsVoipPstnUsers on s.PartyId equals "+" + evpu.DN
  253:                              join eo in db.EmsOnts on evpu.EmsOnt.Id equals eo.Id
  254:                              select eo.Id).AsNoTracking().ToList();
  255:  
  256:                 var list3 = list0.Concat(list1).ToList();
  257:  
  258:                 var ontIdToOntDictionary = Ia.Ftn.Cl.Models.Data.NetworkDesignDocument.OntIdToOntDictionary;
  259:  
  260:                 foreach (var id in list3)
  261:                 {
  262:                     if (ontIdToOntDictionary.ContainsKey(id))
  263:                     {
  264:                         list.Add(ontIdToOntDictionary[id].Ip);
  265:                     }
  266:                 }
  267:             }
  268:  
  269:             foreach (string ip in list)
  270:             {
  271:                 if (ontListNokiaIpToPrimarySwitchImsFsdbDictionary.ContainsKey(ip))
  272:                 {
  273:                     imsFsdb = ontListNokiaIpToPrimarySwitchImsFsdbDictionary[ip];
  274:  
  275:                     if (dictionary.ContainsKey(imsFsdb)) dictionary[imsFsdb]++;
  276:                     else dictionary[imsFsdb] = 1;
  277:                 }
  278:             }
  279:  
  280:             list.Clear();
  281:  
  282:             foreach (KeyValuePair<string, int> kvp in dictionary)
  283:             {
  284:                 list.Add(kvp.Key + ": " + kvp.Value);
  285:             }
  286:  
  287:             return list;
  288:         }
  289:  
  290:         ////////////////////////////////////////////////////////////////////////////
  291:  
  292:         /// <summary>
  293:         ///
  294:         /// </summary>
  295:         public static int NextVacantFlatTermIdFromAgcfEndpointUsingGwId(Ia.Ftn.Cl.Models.Business.Nokia.Ont.FamilyType familyType, int gwId)
  296:         {
  297:             int ft;
  298:             List<int> list;
  299:  
  300:             list = Ia.Ftn.Cl.Models.Data.Nokia.AgcfEndpoint.UsedFlatTermIdListForGatewayId(gwId);
  301:  
  302:             if (list.Count == 0) ft = 1; // this means agcfEndpoint does not exist for any number and the box is empty, and we should create agcfEndpoint at 1
  303:             else
  304:             {
  305:                 // change this later to accommodate the Huawei ONT type
  306:                 list = Ia.Cl.Models.Default.ExcludedNumberListFromNumberListWithinRange(list, Ia.Ftn.Cl.Models.Business.Nokia.Ont.PossibleNumberOfTdForOntFamilyType(familyType));
  307:  
  308:                 if (list.Count > 0) ft = list[0];
  309:                 else ft = 0; // something went wrong
  310:             }
  311:  
  312:             return ft;
  313:         }
  314:  
  315:         ////////////////////////////////////////////////////////////////////////////
  316:  
  317:         /// <summary>
  318:         /// Check the number of combined AGCF gateway records for this MGC IP and its secondary MGC IP if they exceed the MaximumCombinedNumberOfAgcfGatewayRecordsInAnyMgcIpAndMgcSecondaryIpPair 
  319:         /// </summary>
  320:         public static bool MaximumCombinedNumberOfAgcfGatewayRecordsInAnyMgcIpAndMgcSecondaryIpPairIsExceeded(string mgcIp)
  321:         {
  322:             bool isExceeded;
  323:             int count;
  324:             ImsBasicService imsBasicServiceItem;
  325:  
  326:             imsBasicServiceItem = ImsBasicServiceItem(mgcIp);
  327:  
  328:             if (imsBasicServiceItem != null)
  329:             {
  330:                 using (var db = new Ia.Ftn.Cl.Db())
  331:                 {
  332:                     count = (from gr in db.AgcfGatewayRecords
  333:                              where gr.MateExternalIPAddr == imsBasicServiceItem.MgcIp || gr.MateExternalIPAddr == imsBasicServiceItem.MgcSecondaryIp
  334:                              select gr.Id).Count();
  335:  
  336:                     isExceeded = (count > MaximumCombinedNumberOfAgcfGatewayRecordsInAnyMgcIpAndMgcSecondaryIpPair);
  337:                 }
  338:             }
  339:             else throw new System.ArgumentException("imsBasicServiceItem cannot be null", "imsBasicServiceItem");
  340:  
  341:             return isExceeded;
  342:         }
  343:  
  344:         ////////////////////////////////////////////////////////////////////////////
  345:  
  346:         /// <summary>
  347:         /// Statistics dictionary of the current AGCF Gateway Record by MGC gateway IP
  348:         /// </summary>
  349:         public static Dictionary<string, int> NumberOfAgcfGatewayRecordInGroupOfMgcIpDictionary
  350:         {
  351:             get
  352:             {
  353:                 Dictionary<string, int> dictionary;
  354:  
  355:                 using (var db = new Ia.Ftn.Cl.Db())
  356:                 {
  357:                     dictionary = (from gr in db.AgcfGatewayRecords
  358:                                   group gr.MateExternalIPAddr by gr.MateExternalIPAddr into g
  359:                                   select new { MateExternalIPAddr = g.Key, Count = g.Count() }).AsNoTracking().ToDictionary(t => t.MateExternalIPAddr, t => t.Count);
  360:                 }
  361:  
  362:                 return dictionary;
  363:             }
  364:         }
  365:  
  366:         ////////////////////////////////////////////////////////////////////////////
  367:  
  368:         /// <summary>
  369:         /// Statistics dictionary of the current AGCF gateway records with corresponding AGCF endpoints by MGC gateway IP
  370:         /// </summary>
  371:         public static Dictionary<string, int> NumberOfAgcfGatewayRecordWithCorrespondingAgcfEndpointInGroupOfMgcIpDictionary
  372:         {
  373:             get
  374:             {
  375:                 Dictionary<string, int> dictionary;
  376:  
  377:                 using (var db = new Ia.Ftn.Cl.Db())
  378:                 {
  379:                     dictionary = (from gr in db.AgcfGatewayRecords
  380:                                   join ep in db.AgcfEndpoints on new { gr.Id } equals new { ep.AgcfGatewayRecord.Id }
  381:                                   group gr.MateExternalIPAddr by gr.MateExternalIPAddr into g
  382:                                   select new { MateExternalIPAddr = g.Key, Count = g.Count() }).ToDictionary(t => t.MateExternalIPAddr, t => t.Count);
  383:                 }
  384:  
  385:                 return dictionary;
  386:             }
  387:         }
  388:  
  389:         ////////////////////////////////////////////////////////////////////////////
  390:  
  391:         /// <summary>
  392:         /// Calculate a pseudo random MGC IP from imsBasicServiceList for this ONT IP
  393:         /// </summary>
  394:         public static string PseudoRandomMgcIp(string ontIp)
  395:         {
  396:             uint ui, randomIndex;
  397:             string mgcIp;
  398:  
  399:             if (!string.IsNullOrEmpty(ontIp))
  400:             {
  401:                 ui = Ia.Cl.Models.Default.IpToUint(ontIp);
  402:  
  403:                 // important: any change to imsBasicServiceList length will cause the pseudo random function to produce different values for IPs
  404:                 randomIndex = ui % (uint)ImsBasicServiceList.Count();
  405:  
  406:                 mgcIp = ImsBasicServiceList[randomIndex].MgcIp;
  407:             }
  408:             else mgcIp = string.Empty;
  409:  
  410:             return mgcIp;
  411:         }
  412:  
  413:         ////////////////////////////////////////////////////////////////////////////
  414:  
  415:         /// <summary>
  416:         /// Return the IMS basic service for given MGC IP
  417:         /// </summary>
  418:         public static ImsBasicService ImsBasicServiceItem(string mgcIp)
  419:         {
  420:             ImsBasicService imsBasicService;
  421:  
  422:             imsBasicService = (from ibs in ImsBasicServiceList where ibs.MgcIp == mgcIp select ibs).SingleOrDefault();
  423:  
  424:             return imsBasicService;
  425:         }
  426:  
  427:         ////////////////////////////////////////////////////////////////////////////
  428:  
  429:         /// <summary>
  430:         ///
  431:         /// </summary>
  432:         public static string ImsFsdb(int imsService, string primarySwitch)
  433:         {
  434:             string fsdb;
  435:             ImsBasicService imsBasicService;
  436:  
  437:             if (imsService >= 0)
  438:             {
  439:                 imsBasicService = (from ibs in ImsBasicServiceList where ibs.Service == imsService && ibs.PrimarySwitch == primarySwitch select ibs).SingleOrDefault();
  440:  
  441:                 fsdb = (imsBasicService != null) ? imsBasicService.Fsdb : string.Empty;
  442:             }
  443:             else fsdb = string.Empty;
  444:  
  445:             return fsdb;
  446:         }
  447:  
  448:         ////////////////////////////////////////////////////////////////////////////
  449:  
  450:         /// <summary>
  451:         ///
  452:         /// </summary>
  453:         public static string AgcfSipIaPort(int imsService)
  454:         {
  455:             // see ImsServiceFromAgcfSipIaPort()
  456:             string agcfSipIaPort;
  457:  
  458:             switch (imsService)
  459:             {
  460:                 case 0: agcfSipIaPort = "agcf-stdn.imsgroup0-00" + imsService; break;
  461:                 case 1:
  462:                 case 2:
  463:                 case 3: agcfSipIaPort = "agcf-stdo.imsgroup0-00" + imsService; break;
  464:                 case 4:
  465:                 case 5:
  466:                 case 6: agcfSipIaPort = "agcf-stdp.imsgroup0-00" + imsService; break;
  467:                 case 7:
  468:                 case 8:
  469:                 case 9: agcfSipIaPort = "agcf-stdq.imsgroup0-00" + imsService; break;
  470:                 default: agcfSipIaPort = null; break;
  471:             }
  472:  
  473:             return agcfSipIaPort;
  474:         }
  475:  
  476:         ////////////////////////////////////////////////////////////////////////////
  477:  
  478:         /// <summary>
  479:         ///
  480:         /// </summary>
  481:         public static int ImsServiceFromAgcfSipIaPort(string agcfSipIaPort)
  482:         {
  483:             // see AgcfSipIaPort()
  484:             int imsService;
  485:  
  486:             switch (agcfSipIaPort)
  487:             {
  488:                 case "agcf-stdn.imsgroup0-000": imsService = 0; break;
  489:                 case "agcf-stdo.imsgroup0-001": imsService = 1; break;
  490:                 case "agcf-stdo.imsgroup0-002": imsService = 2; break;
  491:                 case "agcf-stdo.imsgroup0-003": imsService = 3; break;
  492:                 case "agcf-stdp.imsgroup0-004": imsService = 4; break;
  493:                 case "agcf-stdp.imsgroup0-005": imsService = 5; break;
  494:                 case "agcf-stdp.imsgroup0-006": imsService = 6; break;
  495:                 case "agcf-stdq.imsgroup0-007": imsService = 7; break;
  496:                 case "agcf-stdq.imsgroup0-008": imsService = 8; break;
  497:                 case "agcf-stdq.imsgroup0-009": imsService = 9; break;
  498:                 default: imsService = -1; break;
  499:             }
  500:  
  501:             return imsService;
  502:         }
  503:  
  504:         ////////////////////////////////////////////////////////////////////////////
  505:  
  506:         /// <summary>
  507:         ///
  508:         /// </summary>
  509:         public static string AlternateFsdbFqdn(string primarySwitch, string fsdb)
  510:         {
  511:             string alternateFsdbFqdn;
  512:  
  513:             if (primarySwitch == TEC)
  514:             {
  515:                 switch (fsdb)
  516:                 {
  517:                     case "fsdb0": alternateFsdbFqdn = "10.16.0.88"; break;
  518:                     case "fsdb1": alternateFsdbFqdn = "10.16.0.89"; break;
  519:                     case "fsdb2": alternateFsdbFqdn = "10.16.0.90"; break;
  520:                     case "fsdb3": alternateFsdbFqdn = "10.16.0.91"; break;
  521:                     default: alternateFsdbFqdn = string.Empty; break;
  522:                 }
  523:             }
  524:             else if (primarySwitch == SKB)
  525:             {
  526:                 switch (fsdb)
  527:                 {
  528:                     case "fsdb0": alternateFsdbFqdn = "10.16.0.9"; break;
  529:                     case "fsdb1": alternateFsdbFqdn = "10.16.0.10"; break;
  530:                     case "fsdb2": alternateFsdbFqdn = "10.16.0.11"; break;
  531:                     case "fsdb3": alternateFsdbFqdn = "10.16.0.12"; break;
  532:                     default: alternateFsdbFqdn = string.Empty; break;
  533:                 }
  534:             }
  535:             else throw new Exception("Unknown primarySwitch") { };
  536:  
  537:             return alternateFsdbFqdn;
  538:         }
  539:  
  540:         ////////////////////////////////////////////////////////////////////////////
  541:  
  542:         /// <summary>
  543:         ///
  544:         /// </summary>
  545:         public static void AssocAndAlternateOtasRealm(string primarySwitch, string fsdb, out int applicationServerId, out string assocOtasRealm, out string alternateOtasRealm)
  546:         {
  547:             bool randomState;
  548:  
  549:             randomState = Ia.Cl.Models.Default.RandomBool;
  550:  
  551:             switch (fsdb)
  552:             {
  553:                 case "fsdb0": applicationServerId = 0; break;
  554:                 case "fsdb1": applicationServerId = randomState ? 1 : 2; break;
  555:                 case "fsdb2": applicationServerId = randomState ? 3 : 4; break;
  556:                 case "fsdb3": applicationServerId = randomState ? 5 : 6; break;
  557:                 default: throw new Exception("Unknown fsdb") { };
  558:             }
  559:  
  560:             if (primarySwitch == TEC)
  561:             {
  562:                 assocOtasRealm = "stas-stdn.fsimsgroup0-00" + applicationServerId + @".tecics01.ims.moc1.kw";
  563:             }
  564:             else if (primarySwitch == SKB)
  565:             {
  566:                 assocOtasRealm = "stas-stdn.fsimsgroup0-00" + applicationServerId + @".skbics01.ims.moc1.kw";
  567:             }
  568:             else throw new Exception("Unknown primarySwitch") { };
  569:  
  570:             //
  571:             if (assocOtasRealm.Contains("skbics01"))
  572:             {
  573:                 alternateOtasRealm = assocOtasRealm.Replace("skbics01", "tecics01");
  574:             }
  575:             else if (assocOtasRealm.Contains("tecics01"))
  576:             {
  577:                 alternateOtasRealm = assocOtasRealm.Replace("tecics01", "skbics01");
  578:             }
  579:             else throw new Exception("Unknown primarySwitch") { };
  580:         }
  581:  
  582:         ////////////////////////////////////////////////////////////////////////////
  583:  
  584:         /// <summary>
  585:         ///
  586:         /// </summary>
  587:         public static string AssigneCorrectMateExternalIPAddrForIsPrimary(bool isPrimary, string mateExternalIPAddr)
  588:         {
  589:             string mate;
  590:  
  591:             if (isPrimary)
  592:             {
  593:                 mate = mateExternalIPAddr;
  594:             }
  595:             else
  596:             {
  597:                 switch (mateExternalIPAddr)
  598:                 {
  599:                     case "10.16.1.31": mate = "10.16.5.31"; break;
  600:                     case "10.16.1.32": mate = "10.16.5.32"; break;
  601:                     case "10.16.1.33": mate = "10.16.5.33"; break;
  602:                     case "10.16.1.34": mate = "10.16.5.34"; break;
  603:                     case "10.16.1.35": mate = "10.16.5.35"; break;
  604:                     case "10.16.1.36": mate = "10.16.5.36"; break;
  605:                     case "10.16.1.37": mate = "10.16.5.37"; break;
  606:                     case "10.16.1.38": mate = "10.16.5.38"; break;
  607:                     case "10.16.1.39": mate = "10.16.5.39"; break;
  608:                     case "10.16.1.40": mate = "10.16.5.40"; break;
  609:  
  610:                     case "10.16.5.31": mate = "10.16.1.31"; break;
  611:                     case "10.16.5.32": mate = "10.16.1.32"; break;
  612:                     case "10.16.5.33": mate = "10.16.1.33"; break;
  613:                     case "10.16.5.34": mate = "10.16.1.34"; break;
  614:                     case "10.16.5.35": mate = "10.16.1.35"; break;
  615:                     case "10.16.5.36": mate = "10.16.1.36"; break;
  616:                     case "10.16.5.37": mate = "10.16.1.37"; break;
  617:                     case "10.16.5.38": mate = "10.16.1.38"; break;
  618:                     case "10.16.5.39": mate = "10.16.1.39"; break;
  619:                     case "10.16.5.40": mate = "10.16.1.40"; break;
  620:  
  621:                     default: mate = null; break;
  622:                 }
  623:             }
  624:  
  625:             return mate;
  626:         }
  627:  
  628:         ////////////////////////////////////////////////////////////////////////////
  629:  
  630:         /// <summary>
  631:         ///
  632:         /// </summary>
  633:         public static string PrimarySwitchFromAgcfGatewayRecord(bool isPrimary)
  634:         {
  635:             string primarySwitch;
  636:  
  637:             if (isPrimary) primarySwitch = Ia.Ftn.Cl.Models.Business.Nokia.Ims.AnyPrimarySwitch;
  638:             else primarySwitch = Ia.Ftn.Cl.Models.Business.Nokia.Ims.SKB;
  639:  
  640:             return primarySwitch;
  641:         }
  642:  
  643:         ////////////////////////////////////////////////////////////////////////////
  644:  
  645:         /// <summary>
  646:         ///
  647:         /// </summary>
  648:         public static string SecondarySwitchFromAgcfGatewayRecord(bool isPrimary)
  649:         {
  650:             string secondarySwitch;
  651:  
  652:             if (!isPrimary) secondarySwitch = Ia.Ftn.Cl.Models.Business.Nokia.Ims.AnyPrimarySwitch;
  653:             else secondarySwitch = Ia.Ftn.Cl.Models.Business.Nokia.Ims.SKB;
  654:  
  655:             return secondarySwitch;
  656:         }
  657:  
  658:         ////////////////////////////////////////////////////////////////////////////
  659:  
  660:         /// <summary>
  661:         ///
  662:         /// </summary>
  663:         public static int ServiceProfileNumber(int applicationServerId)
  664:         {
  665:             int serviceProfileNumber;
  666:  
  667:             switch (applicationServerId)
  668:             {
  669:                 case 0: serviceProfileNumber = 2; break;
  670:                 case 1: serviceProfileNumber = 10; break;
  671:                 case 2: serviceProfileNumber = 18; break;
  672:                 case 3: serviceProfileNumber = 26; break;
  673:                 case 4: serviceProfileNumber = 34; break;
  674:                 case 5: serviceProfileNumber = 42; break;
  675:                 case 6: serviceProfileNumber = 50; break;
  676:                 default: throw new Exception("Unknown primarySwitch") { };
  677:             }
  678:  
  679:             return serviceProfileNumber;
  680:         }
  681:  
  682:         ////////////////////////////////////////////////////////////////////////////
  683:  
  684:         /// <summary>
  685:         ///
  686:         /// </summary>
  687:         public static int ServiceProfileNumberAgcfGatewayRecord(int imsService)
  688:         {
  689:             bool randomState;
  690:             int serviceProfileNumber;
  691:  
  692:             randomState = Ia.Cl.Models.Default.RandomBool;
  693:  
  694:             switch (imsService)
  695:             {
  696:                 case 0: serviceProfileNumber = 2; break;
  697:                 case 1:
  698:                 case 2:
  699:                 case 3: serviceProfileNumber = randomState ? 10 : 18; break;
  700:                 case 4:
  701:                 case 5:
  702:                 case 6: serviceProfileNumber = randomState ? 26 : 34; break;
  703:                 case 7:
  704:                 case 8:
  705:                 case 9: serviceProfileNumber = randomState ? 42 : 50; break;
  706:                 default: throw new Exception("Unknown primarySwitch") { };
  707:             }
  708:  
  709:             return serviceProfileNumber;
  710:         }
  711:  
  712:         ////////////////////////////////////////////////////////////////////////////
  713:  
  714:         /// <summary>
  715:         ///
  716:         /// </summary>
  717:         public static int GwIdToReadAgcfGatewayRecordData(ref int referenceIndex, out int itemIndex, out int listCount)
  718:         {
  719:             if (allPossibleGwIdList.JustStartedOrRolledOver())
  720:             {
  721:                 allPossibleGwIdList = Ia.Ftn.Cl.Models.Data.Nokia.Ims.AllPossibleGatewayIdList;
  722:             }
  723:  
  724:             var number = allPossibleGwIdList.Next(ref referenceIndex, out itemIndex, out listCount);
  725:  
  726:             return number;
  727:         }
  728:  
  729:         ////////////////////////////////////////////////////////////////////////////
  730:  
  731:         /// <summary>
  732:         ///
  733:         /// </summary>
  734:         public static string ServiceToReadServiceData(ref int referenceIndex, out int itemIndex, out int listCount)
  735:         {
  736:             if (allPossibleServiceNumberList.JustStartedOrRolledOver())
  737:             {
  738:                 allPossibleServiceNumberList = Ia.Ftn.Cl.Models.Data.Service.AllPossibleServiceNumberListWithinNokiaSwitch;
  739:             }
  740:  
  741:             var service = allPossibleServiceNumberList.Next(ref referenceIndex, out itemIndex, out listCount);
  742:  
  743:             return service.ToString();
  744:         }
  745:  
  746:         ////////////////////////////////////////////////////////////////////////////
  747:  
  748:         /// <summary>
  749:         ///
  750:         /// </summary>
  751:         public static string SequentialPrividUserFromAgcfEndpointToReadSubPartyAndSubscriberData
  752:         {
  753:             get
  754:             {
  755:                 string prividUser;
  756:  
  757:                 if (agcfEndpointPrividUserQueue.Count == 0)
  758:                 {
  759:                     agcfEndpointPrividUserQueue = new Queue<string>(Ia.Ftn.Cl.Models.Data.Nokia.AgcfEndpoint.ReadPrividUserList);
  760:                 }
  761:  
  762:                 prividUser = agcfEndpointPrividUserQueue.Dequeue();
  763:  
  764:                 return prividUser;
  765:             }
  766:         }
  767:  
  768:         ////////////////////////////////////////////////////////////////////////////
  769:         ////////////////////////////////////////////////////////////////////////////
  770:  
  771:         /// <summary>
  772:         ///
  773:         /// </summary>
  774:         public static Ia.Cl.Models.Result CreateMissingAgcfGatewayRecordForNokiaSwitchOntInNonSipOlt(Ia.Ftn.Cl.Models.Client.Nokia.Ims nokiaIms)
  775:         {
  776:             string r1;
  777:  
  778:             var result = new Ia.Cl.Models.Result();
  779:  
  780:             var nddOnt = Ia.Ftn.Cl.Models.Data.Provision.NddNokiaSwitchOntInNonSipOltWithAccessButNoAgcfGatewayRecord(out string r0);
  781:  
  782:             if (nddOnt != null)
  783:             {
  784:                 var gwId = Ia.Ftn.Cl.Models.Business.Nokia.AgcfGatewayRecord.RandomUnusedGwId();
  785:  
  786:                 Ia.Ftn.Cl.Models.Data.Nokia.Ims.CreateAgcfGatewayRecordForGwId(nokiaIms, gwId, nddOnt, out string createResult);
  787:  
  788:                 Ia.Ftn.Cl.Models.Data.Nokia.Ims.ReadUpdateAgcfGatewayRecordAndAgcfEndpointListAndSubPartyAndSubscriberAndServiceForGwId(nokiaIms, gwId, out string readResult);
  789:  
  790:                 r1 = r0 + " " + nddOnt.Access.Name + ", gwId: " + gwId + ", createResult: " + createResult + ", readResult: " + readResult;
  791:             }
  792:             else
  793:             {
  794:                 r1 = "There are no Nokia switch non SIP OLT NDD ONTs with access and without an AgcfGatewayRecord. ";
  795:             }
  796:  
  797:             result.AddSuccess(r1);
  798:  
  799:             return result;
  800:         }
  801:  
  802:         ////////////////////////////////////////////////////////////////////////////
  803:  
  804:         /// <summary>
  805:         ///
  806:         /// </summary>
  807:         public static Ia.Cl.Models.Result DeleteAgcfGatewayRecordWithNoNddNokiaSwitchOntInNonSipOltAndNullOrEmptyAgcfEndpoint(Ia.Ftn.Cl.Models.Client.Nokia.Ims nokiaIms)
  808:         {
  809:             var r0 = string.Empty;
  810:             var result = new Ia.Cl.Models.Result();
  811:  
  812:             var agcfGatewayRecord = Ia.Ftn.Cl.Models.Data.Provision.AgcfGatewayRecordWithNoNddNokiaSwitchOntInNonSipOltAndNullOrEmptyAgcfEndpoint(out string r1);
  813:  
  814:             try
  815:             {
  816:                 if (agcfGatewayRecord != null)
  817:                 {
  818:                     Ia.Ftn.Cl.Models.Data.Nokia.Ims.DeleteAgcfGatewayRecordForGwId(nokiaIms, agcfGatewayRecord, out string deleteResult);
  819:  
  820:                     Ia.Ftn.Cl.Models.Data.Nokia.Ims.ReadUpdateAgcfGatewayRecordAndAgcfEndpointListAndSubPartyAndSubscriberAndServiceForGwId(nokiaIms/*, null*/, agcfGatewayRecord.GwId, out string readResult);
  821:  
  822:                     r0 = "GwId: " + agcfGatewayRecord.GwId + ", deleteResult: " + deleteResult + ", readResult: " + readResult;
  823:                 }
  824:                 else
  825:                 {
  826:                     r0 = "There are no AgcfGatewayRecords with no Nokia switch, non SIP OLT NDD ONTs and with null or empty AgcfEndpoint. ";
  827:                 }
  828:             }
  829:             catch (Exception)
  830:             {
  831:                 r0 = "Exception: " + r0;
  832:             }
  833:  
  834:             r0 = r1 + " " + r0;
  835:             result.AddSuccess(r0);
  836:  
  837:             return result;
  838:         }
  839:  
  840:         ////////////////////////////////////////////////////////////////////////////
  841:  
  842:         /// <summary>
  843:         ///
  844:         /// </summary>
  845:         private void ManageNokiaUpdateAgcfGatewayRecord(Ia.Ftn.Cl.Models.Client.Nokia.Ims nokiaIms, out string result)
  846:         {
  847:             string r1;
  848:             int gwId;
  849:             Ia.Ftn.Cl.Models.Business.NetworkDesignDocument.Ont nddOnt;
  850:             Ia.Ftn.Cl.Models.Nokia.AgcfGatewayRecord agcfGatewayRecord;
  851:  
  852:             r1 = string.Empty;
  853:             result = string.Empty;
  854:  
  855:             agcfGatewayRecord = Ia.Ftn.Cl.Models.Data.Nokia.AgcfGatewayRecord.ListByMateExternalIPAddr("10.16.1.36").PickRandom();
  856:  
  857:             try
  858:             {
  859:                 if (agcfGatewayRecord != null)
  860:                 {
  861:                     gwId = agcfGatewayRecord.GwId;
  862:                     nddOnt = Ia.Ftn.Cl.Models.Data.NetworkDesignDocument.OntByIp(agcfGatewayRecord.IP1);
  863:                     //nddOnt = (from no in Ia.Ftn.Cl.Model.Data.NetworkDesignDocument.OntList where no.Ip == agcfGatewayRecord.IP1 select no).SingleOrDefault();
  864:  
  865:                     if (nddOnt != null)
  866:                     {
  867:                         nokiaIms.EdNgfsAgcfGatewayRecordV2_MateExternalIPAddr(gwId, "10.16.5.36", nddOnt, out Ia.Ftn.Cl.Models.Business.Nokia.Ims.Response response);
  868:  
  869:                         Ia.Ftn.Cl.Models.Data.Nokia.Ims.ReadUpdateAgcfGatewayRecordAndAgcfEndpointListAndSubPartyAndSubscriberAndServiceForGwId(nokiaIms, gwId, out result);
  870:  
  871:                         result = nddOnt.Access.Name + ", gwId: " + gwId + ", ResultCode: " + response.ResultCode.ToString() + ", result: " + result.ToString();
  872:                     }
  873:                     else
  874:                     {
  875:                         result = "nddOnt null. ";
  876:                     }
  877:                 }
  878:                 else
  879:                 {
  880:                     result = "agcfGatewayRecord is null. ";
  881:                 }
  882:             }
  883:             catch (Exception)
  884:             {
  885:                 result = "Exception: " + result;
  886:             }
  887:  
  888:             result = "Updated: " + r1 + " " + result;
  889:         }
  890:  
  891:         ////////////////////////////////////////////////////////////////////////////
  892:  
  893:         /// <summary>
  894:         ///
  895:         /// </summary>
  896:         private void DeleteAgcfGatewayRecordList(Ia.Ftn.Cl.Models.Client.Nokia.Ims nokiaIms, List<int> list, out string result)
  897:         {
  898:             string primarySwitch;
  899:             //Ia.Ftn.Cl.Model.Nokia.AgcfGatewayRecord agcfGatewayRecord;
  900:  
  901:             result = string.Empty;
  902:  
  903:             try
  904:             {
  905:                 foreach (int gwId in list)
  906:                 {
  907:                     //agcfGatewayRecord = Ia.Ftn.Cl.Model.Nokia.AgcfGatewayRecord.ReadByGwId(0);
  908:  
  909:                     //if (agcfGatewayRecord != null)
  910:                     //{
  911:                     primarySwitch = Ia.Ftn.Cl.Models.Business.Nokia.Ims.SKB;// Ia.Ftn.Cl.Model.Business.Nokia.Ims.PrimarySwitchFromAgcfGatewayRecord(agcfGatewayRecord.IsPrimary);
  912:  
  913:                     nokiaIms.DltNgfsAgcfGwCombinedRecV2(gwId, primarySwitch, out Ia.Ftn.Cl.Models.Business.Nokia.Ims.Response response);
  914:  
  915:                     Ia.Ftn.Cl.Models.Data.Nokia.Ims.ReadUpdateAgcfGatewayRecordAndAgcfEndpointListAndSubPartyAndSubscriberAndServiceForGwId(nokiaIms/*, null*/, gwId, out result);
  916:  
  917:                     result = "GwId: " + gwId + ", dltResultCode: " + response.ResultCode.ToString() + ", result: " + result.ToString();
  918:                     //}
  919:                     //else
  920:                     //{
  921:                     //    result = "agcfGatewayRecord is null. ";
  922:                     //}
  923:                 }
  924:             }
  925:             catch (Exception)
  926:             {
  927:                 result = "Exception: " + result;
  928:             }
  929:  
  930:             result = "Delete AgcfGatewayRecord list: " + result;
  931:         }
  932:  
  933:         ////////////////////////////////////////////////////////////////////////////
  934:         ////////////////////////////////////////////////////////////////////////////
  935:  
  936:         /// <summary>
  937:         ///
  938:         /// </summary>
  939:         public static void ManageModifyNokiaSwitchSubscriberH248ToSip(Ia.Ftn.Cl.Models.Client.Nokia.Ims ims, out Ia.Cl.Models.Result result)
  940:         {
  941:             string r;
  942:             Ia.Ftn.Cl.Models.Business.Procedure.Process process;
  943:  
  944:             result = new Ia.Cl.Models.Result();
  945:  
  946:             process = procedureNokiaImsSubscriberToBeUpdatedFromH248ToSipList.NextProcess();
  947:  
  948:             if (process.Type != Ia.Ftn.Cl.Models.Business.Procedure.ProcessType.None)
  949:             {
  950:                 if (process.Type == Ia.Ftn.Cl.Models.Business.Procedure.ProcessType.DeleteRead)
  951:                 {
  952:                     result.AddSuccess("delete-read H.248: " + process.Ont.Access.Name + " " + procedureNokiaImsSubscriberToBeUpdatedFromH248ToSipList.ProgressCounterString);
  953:  
  954:                     Ia.Ftn.Cl.Models.Business.Provision.DeleteReadNokiaSwitchSubscriber(ims, process.Ont.Access.Name, process.Service, process.Protocol, false, out r);
  955:  
  956:                     result.AddSuccess(r);
  957:                 }
  958:                 else if (process.Type == Ia.Ftn.Cl.Models.Business.Procedure.ProcessType.CreateRead)
  959:                 {
  960:                     result.AddSuccess("create-read SIP: " + process.Ont.Access.Name + " " + procedureNokiaImsSubscriberToBeUpdatedFromH248ToSipList.ProgressCounterString);
  961:  
  962:                     Ia.Ftn.Cl.Models.Business.Provision.CreateReadNokiaSwitchSubscriber(ims, process.Ont.Access.Name, process.Service, Ia.Ftn.Cl.Models.Business.Default.PortUndefinedOrInvalidOrUnknown, process.Protocol, false, out r);
  963:  
  964:                     result.AddSuccess(r);
  965:                 }
  966:                 else result.AddSuccess("delete-read, create-read: undefined procedure. ");
  967:             }
  968:             else result.AddSuccess("delete-read, create-read: nothing to update");
  969:         }
  970:  
  971:         ////////////////////////////////////////////////////////////////////////////
  972:         ////////////////////////////////////////////////////////////////////////////
  973:  
  974:         /// <summary>
  975:         ///
  976:         /// </summary>
  977:         public static bool TemporaryProcedureToDetectASessionInvalidAndStopProcessing(Ia.Cl.Models.Result result)
  978:         {
  979:             bool b;
  980:  
  981:             b = result.Message.Contains("SessionInvalid") || result.Message.Contains("Session");
  982:  
  983:             return b;
  984:         }
  985:  
  986:         ////////////////////////////////////////////////////////////////////////////
  987:         ////////////////////////////////////////////////////////////////////////////
  988:     }
  989:  
  990:     ////////////////////////////////////////////////////////////////////////////
  991:     ////////////////////////////////////////////////////////////////////////////
  992: }