1: using System;
2: using System.Collections.Generic;
3: using System.IO;
4: using System.Linq;
5: using System.Text.RegularExpressions;
6:
7: namespace Ia.Ngn.Cl.Model.Business.Siemens
8: {
9: ////////////////////////////////////////////////////////////////////////////
10:
11: /// <summary publish="true">
12: /// Nokia's Siemens EWSD support class of Optical Fiber Network (OFN) business model.
13: /// </summary>
14: ///
15: /// <remarks>
16: /// Copyright © 2018-2021 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
17: ///
18: /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
19: /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
20: ///
21: /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
22: /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
23: ///
24: /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
25: ///
26: /// Copyright notice: This notice may not be removed or altered from any source distribution.
27: /// </remarks>
28: public class Ewsd
29: {
30: private static Queue<int> serviceQueue = new Queue<int>();
31: private static Queue<ProvisioningWorkflow> synchronizationCommandQueue = new Queue<ProvisioningWorkflow>();
32:
33: private static Queue<ProvisioningWorkflow> synchronizationProvisioningWorkflowQueue = new Queue<ProvisioningWorkflow>();
34: private static Queue<ProvisioningWorkflow> serviceSuspentionSynchronizationProvisioningWorkflowQueue = new Queue<ProvisioningWorkflow>();
35:
36: /// <summary/>
37: public enum Opcode { Dispsub, Cansub, UpdateSubXxx, SuspendTemp, Dispkeyword };//, Crcpt, Disptime }
38:
39: /// <summary/>
40: public class ProvisioningWorkflow
41: {
42: /// <summary/>
43: public string Service { get; set; }
44:
45: /// <summary/>
46: public Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pstn Pstn { get; set; }
47:
48: /// <summary/>
49: public string ReadCommand { get; set; }
50:
51: /// <summary/>
52: public string ServiceSuspensionCommand { get; set; }
53:
54: /// <summary/>
55: public string DeleteCommand { get; set; }
56:
57: /// <summary/>
58: public ProvisioningWorkflow()
59: {
60:
61: }
62: }
63:
64: public static List<string> ServiceSymbolList { get; } = new List<string>();
65:
66: ////////////////////////////////////////////////////////////////////////////
67:
68: /// <summary>
69: /// Response of Siemens EWSD
70: /// </summary>
71: public class Response
72: {
73: public int Service { get; set; }
74:
75: /// <summary/>
76: public bool IsSuccess { get { return ReturnCode == Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.Successful; } }
77:
78: /// <summary/>
79: public bool IsProvisioned { get; set; }
80:
81: /// <summary/>
82: public Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode ReturnCode { get; set; }
83:
84: /// <summary/>
85: //public string Ctag { get; set; } // no need because the commad string is included in response body
86:
87: /// <summary/>
88: public DateTime DateTime { get; set; }
89:
90: /// <summary/>
91: public string CommandString { get; set; }
92:
93:
94: /// <summary/>
95: public int Dn { get; set; }
96:
97: /// <summary/>
98: public string Lac { get; set; }
99:
100: /// <summary/>
101: public string Eqn { get; set; }
102:
103: /// <summary/>
104: public string Cat { get; set; }
105:
106: /// <summary/>
107: public string Ltt { get; set; }
108:
109: /// <summary/>
110: public string Optrcl { get; set; }
111:
112: /// <summary/>
113: public string Subtrcl { get; set; }
114:
115: /// <summary/>
116: public string Numcal { get; set; }
117:
118: /// <summary/>
119: public string Orig1 { get; set; }
120:
121: /// <summary/>
122: public string Trarstr { get; set; }
123:
124: /// <summary/>
125: public string Lnatt { get; set; }
126:
127: /// <summary/>
128: public string Div { get; set; }
129:
130: /// <summary/>
131: public string Cos { get; set; }
132:
133: /// <summary/>
134: public string Addinf { get; set; }
135:
136: /// <summary/>
137: public string Numbch { get; set; }
138:
139: /// <summary/>
140: public string Ctdivi { get; set; }
141:
142: /// <summary/>
143: public string Blk { get; set; }
144:
145: /// <summary/>
146: public string Content { get; set; }
147:
148: /// <summary/>
149: public Ia.Ngn.Cl.Model.Business.Service.ServiceSupplementaryService ServiceSupplementaryService { get; set; }
150:
151: ////////////////////////////////////////////////////////////////////////////
152:
153: /// <summary>
154: ///
155: /// </summary>
156: public Response(string content)
157: {
158: int jobNumber, jobEndNumber;
159: string service, fileHead, fileFoot;
160: Match match;
161: Ia.Ngn.Cl.Model.Business.Service.ServiceSupplementaryService serviceSupplementaryService;
162: Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode returnCode;
163:
164: fileHead = "\r\n-----------------------------------------------------------------------------";
165: fileFoot = "-----------------------------------------------------------------------------\r\n";
166:
167: if (content.StartsWith(fileHead) && content.EndsWith(fileFoot))
168: {
169: content = content.Replace(fileHead, "");
170: content = content.Replace(fileFoot, "");
171:
172: match = Regex.Match(content, @"^\s+(\d+)\s+(.+)\s+(\d+)\s+$", RegexOptions.Singleline);
173:
174: if (match.Success)
175: {
176: jobNumber = int.Parse(match.Groups[1].Value);
177: jobEndNumber = int.Parse(match.Groups[3].Value);
178:
179: if (jobNumber == jobEndNumber)
180: {
181: content = match.Groups[2].Value;
182:
183: if (content.Contains("OBJECT NOT CONNECTED"))
184: {
185: /*
186: 9241 MASKNO:10001
187: COMMAND ERROR MESSAGE FOR DISPSUB : 1 ERROR(S)
188: MASKNO:10990
189: OBJECT NOT CONNECTED
190:
191: CNTXT PAR.NAME PARAMETER VALUE
192: -----+--------+---------------------------------------------------------
193: DN =<25420976>
194:
195:
196: END JOB 9241
197: */
198:
199: match = Regex.Match(content, @"DN\s+=<(\d{8})>");
200:
201: if (match.Success)
202: {
203: service = match.Groups[1].Value;
204:
205: this.CommandString = @"DISPSUB:DN=" + service + ";";
206:
207: this.Service = int.Parse(service);
208:
209: this.IsProvisioned = false;
210:
211: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.Successful;
212:
213: this.Dn = int.Parse(service);
214: this.Content = content;
215: this.ReturnCode = returnCode;
216: }
217: else
218: {
219: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.Failed;
220:
221: this.Content = content;
222: this.ReturnCode = returnCode;
223: }
224: }
225: else if (content.Contains("OBJECT NOT A SUBSCRIBER"))
226: {
227: match = Regex.Match(content, @"DN\s+=<(\d{8})>");
228:
229: if (match.Success)
230: {
231: service = match.Groups[1].Value;
232:
233: this.CommandString = @"DISPSUB:DN=" + service + ";";
234:
235: this.Service = int.Parse(service);
236:
237: this.IsProvisioned = true;
238:
239: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.Successful;
240:
241: this.Dn = int.Parse(service);
242: this.Content = content;
243: this.ReturnCode = returnCode;
244:
245: serviceSupplementaryService = new Ia.Ngn.Cl.Model.Business.Service.ServiceSupplementaryService();
246: serviceSupplementaryService.IsPbx = true;
247:
248: this.ServiceSupplementaryService = serviceSupplementaryService;
249: }
250: else
251: {
252: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.Failed;
253:
254: this.Content = content;
255: this.ReturnCode = returnCode;
256: }
257: }
258: else if (content.Contains("DISPSUB") && content.Contains("END JOB"))
259: {
260:
261: /*
262: DISPSUB:DN=23833902;
263:
264: MASKNO:03800
265: LAC = 01 DN = 23833902 EQN = 1350- 0- 4-30
266: CAT = MS MASKNO:03774
267: LTT = COSLAC2 MASKNO:03789
268: OPTRCL = 2 MASKNO:03798
269: NUMCAL = 1 MASKNO:08641
270: ORIG1 = 5
271: DIV = DIVI DIVIMOD DDVIN MASKNO:08598
272: LNATT = PB MASKNO:03787
273: COS = ACTCW CONF3 CWACT PROP8 CLIP MASKNO:03777
274: FSK
275:
276:
277: END JOB 9232
278: */
279:
280: match = Regex.Match(content, @"DISPSUB:DN=(\d{8});");
281:
282: if (match.Success)
283: {
284: service = match.Groups[1].Value;
285:
286: this.CommandString = @"DISPSUB:DN=" + service + ";";
287:
288: this.Service = int.Parse(service);
289:
290: this.IsProvisioned = true;
291:
292: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.Successful;
293:
294: this.Content = content;
295: this.ReturnCode = returnCode;
296:
297: this.ParseDispsub(content, out int dn, out string lac, out string eqn, out string cat, out string ltt, out string optrcl, out string subtrcl, out string numcal, out string orig1, out string trarstr, out string lnatt, out string div, out string cos, out string addinf, out string numbch, out string ctdivi, out string blk);
298: this.Dn = dn;
299: this.Lac = lac;
300: this.Eqn = eqn;
301: this.Cat = cat;
302: this.Ltt = ltt;
303: this.Optrcl = optrcl;
304: this.Subtrcl = subtrcl;
305: this.Numcal = numcal;
306: this.Orig1 = orig1;
307: this.Trarstr = trarstr;
308: this.Lnatt = lnatt;
309: this.Div = div;
310: this.Cos = cos;
311: this.Addinf = addinf;
312: this.Numbch = numbch;
313: this.Ctdivi = ctdivi;
314: this.Blk = blk;
315:
316: serviceSupplementaryService = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ServiceSupplementaryServiceStateFromServiceNetManagerOutputString(content);
317:
318: this.ServiceSupplementaryService = serviceSupplementaryService;
319: }
320: else
321: {
322: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.Failed;
323:
324: this.Content = content;
325: this.ReturnCode = returnCode;
326: }
327: }
328: else
329: {
330: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.NotAcceptedUnreasonableValue;
331:
332: this.Content = content;
333: this.ReturnCode = returnCode;
334: }
335: }
336: else
337: {
338: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.FileFormatError;
339:
340: this.Content = content;
341: this.ReturnCode = returnCode;
342: }
343: }
344: else
345: {
346: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.FileFormatError;
347:
348: this.Content = content;
349: this.ReturnCode = returnCode;
350: }
351: }
352: else
353: {
354: returnCode = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ResultCode.FileFormatError;
355:
356: this.Content = content;
357: this.ReturnCode = returnCode;
358: }
359: }
360:
361: ////////////////////////////////////////////////////////////////////////////
362:
363: /// <summary>
364: ///
365: /// </summary>
366: private void ParseDispsub(string suscpOutputContent, out int dn, out string lac, out string eqn, out string cat, out string ltt, out string optrcl, out string subtrcl, out string numcal, out string orig1, out string trarstr, out string lnatt, out string div, out string cos, out string addinf, out string numbch, out string ctdivi, out string blk)
367: {
368: int dn2;
369:
370: using (StringReader stringReader = new StringReader(suscpOutputContent))
371: {
372: string line;
373: dn = -1;
374: lac = eqn = cat = ltt = optrcl = subtrcl = numcal = orig1 = trarstr = lnatt = div = cos = addinf = numbch = ctdivi = blk = string.Empty;
375:
376: while ((line = stringReader.ReadLine()) != null)
377: {
378: // remove "MASKNO:03774"
379: line = Regex.Replace(line, @"MASKNO:\d+\s+", "");
380:
381: //DISPSUB:DN=23833902;
382: if (line.StartsWith("DISPSUB")) dn = int.Parse(Regex.Match(line, @"^DISPSUB:DN=(\d{8});").Groups[1].Value);
383: else if (line.StartsWith("LAC"))
384: {
385: lac = Regex.Match(line, @"LAC\s+=\s+(.+?)\s+").Groups[1].Value;
386:
387: dn2 = int.Parse(Regex.Match(line, @"DN\s+=\s+(\d{8})\s+").Groups[1].Value);
388:
389: if (dn != dn2) throw new ArgumentException("dn != dn2");
390:
391: eqn = Regex.Match(line, @"EQN\s+=\s+(.+)\s+").Groups[1].Value;
392: }
393: else if (line.StartsWith(" CAT")) cat = ThreeSpaceTermEntryValue(line, "CAT");
394: else if (line.StartsWith(" LTT")) ltt = ThreeSpaceTermEntryValue(line, "LTT");
395: else if (line.StartsWith(" OPTRCL")) optrcl = ThreeSpaceTermEntryValue(line, "OPTRCL");
396: else if (line.StartsWith(" SUBTRCL")) subtrcl = ThreeSpaceTermEntryValue(line, "SUBTRCL");
397: else if (line.StartsWith(" NUMCAL")) numcal = ThreeSpaceTermEntryValue(line, "NUMCAL");
398: else if (line.StartsWith(" ORIG1")) orig1 = ThreeSpaceTermEntryValue(line, "ORIG1");
399: else if (line.StartsWith(" TRARSTR")) trarstr = ThreeSpaceTermEntryValue(line, "TRARSTR");
400: else if (line.StartsWith(" LNATT")) lnatt = ThreeSpaceTermEntryValue(line, "LNATT");
401: else if (line.StartsWith(" DIV")) div = ThreeSpaceTermEntryValue(line, "DIV");
402: else if (line.StartsWith(" COS")) cos = ThreeSpaceTermEntryValue(line, "COS");
403: else if (line.StartsWith(" ADDINF")) addinf = ThreeSpaceTermEntryValue(line, "ADDINF");
404: else if (line.StartsWith(" NUMBCH")) numbch = ThreeSpaceTermEntryValue(line, "NUMBCH");
405: else if (line.StartsWith(" CTDIVI")) ctdivi = ThreeSpaceTermEntryValue(line, "CTDIVI");
406: else if (line.StartsWith(" BLK")) blk = ThreeSpaceTermEntryValue(line, "BLK");
407: else
408: {
409: }
410: }
411: }
412: }
413:
414: ////////////////////////////////////////////////////////////////////////////
415: ////////////////////////////////////////////////////////////////////////////
416: }
417:
418: ////////////////////////////////////////////////////////////////////////////
419:
420: /// <summary>
421: ///
422: /// </summary>
423: private static string ThreeSpaceTermEntryValue(string line, string term)
424: {
425: string s;
426:
427: s = Regex.Match(line, @"^\s+" + term + @"\s+=\s+(.+)\s+").Groups[1].Value;
428:
429: s = s.Trim();
430:
431: // replace spaces with ','
432: s = Regex.Replace(s, @"\s+", ",");
433:
434: return s;
435: }
436:
437: ////////////////////////////////////////////////////////////////////////////
438:
439: /// <summary>
440: ///
441: /// </summary>
442: public enum ResultCode
443: {
444: Successful = 0,
445: Failed = 1,
446: ObjectNotASubscriber = 2,
447: ObjectNotConnected = 3,
448: NotAcceptedUnreasonableValue = 4,
449: NotAcceptedCommandUnknown = 5,
450: FileFormatError = 6,
451: }
452:
453: ////////////////////////////////////////////////////////////////////////////
454:
455: /// <summary>
456: ///
457: /// </summary>
458: public Ewsd() { }
459:
460: ////////////////////////////////////////////////////////////////////////////
461:
462: /// <summary>
463: ///
464: /// </summary>
465: public static int ProperlySelectedSingleServiceQueueServiceNumber(List<Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pstn> pstnList)
466: {
467: int service;
468: List<int> list;
469:
470: service = 0;
471:
472: if (serviceQueue.Count == 0)
473: {
474: list = AllPossibleServiceNumbersPreferablyNotInEwsdSubscriberWithinPstn(pstnList);
475:
476: serviceQueue = new Queue<int>(list.Shuffle()); //.OrderBy(o => o));
477: }
478:
479: if (serviceQueue.Count > 0) service = serviceQueue.Dequeue();
480:
481: return service;
482: }
483:
484: ////////////////////////////////////////////////////////////////////////////
485:
486: /// <summary>
487: ///
488: /// </summary>
489: public static List<int> AllPossibleServiceNumbersPreferablyNotInEwsdSubscriberWithinPstn(List<Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pstn> pstnList)
490: {
491: var allPossibleServiceNumbersWithinPstn = new List<int>();
492:
493: foreach (var pstn in pstnList)
494: {
495: allPossibleServiceNumbersWithinPstn.AddRange(Ia.Ngn.Cl.Model.Data.Service.AllPossibleServiceNumbersWithinPstn(pstn.Name));
496: }
497:
498: var dnList = Ia.Ngn.Cl.Model.Data.Siemens.Subscriber.DnList();
499:
500: var list = allPossibleServiceNumbersWithinPstn.Except(dnList).ToList();
501:
502: // if list is empty then will use the all list
503: if (list.Count == 0) list = allPossibleServiceNumbersWithinPstn;
504:
505: var hashSet = new HashSet<int>(list);
506:
507: return hashSet.OrderBy(u => u).ToList();
508: }
509:
510: ////////////////////////////////////////////////////////////////////////////
511:
512: /// <summary>
513: ///
514: /// </summary>
515: public static ProvisioningWorkflow DeleteAndReadEwsdServiceQueueCommand(Ia.Ngn.Cl.Model.Business.Default.Procedure procedure)
516: {
517: ProvisioningWorkflow provisioningWorkflow;
518: List<ProvisioningWorkflow> list;
519:
520: provisioningWorkflow = null;
521:
522: if (synchronizationCommandQueue.Count == 0 && procedure == Ia.Ngn.Cl.Model.Business.Default.Procedure.InitializeOrIterate)
523: {
524: list = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.DeleteAndReadEwsdServiceCommandList();
525:
526: synchronizationCommandQueue = new Queue<ProvisioningWorkflow>(list); // don't shuffle because a modify command is followed by a read .Shuffle());
527: }
528:
529: if (synchronizationCommandQueue.Count > 0) provisioningWorkflow = synchronizationCommandQueue.Dequeue();
530:
531: return provisioningWorkflow;
532: }
533:
534: ////////////////////////////////////////////////////////////////////////////
535:
536: /// <summary>
537: ///
538: /// </summary>
539: public static List<ProvisioningWorkflow> DeleteAndReadEwsdServiceCommandList()
540: {
541: ProvisioningWorkflow provisioningWorkflow;
542: List<ProvisioningWorkflow> provisioningWorkflowList;
543:
544: provisioningWorkflowList = new List<ProvisioningWorkflow>();
545:
546: //var imsServiceToRouterVendorDictionary0 = Ia.Ngn.Cl.Model.Data.Service.ImsServiceToOntRouterVendorInAllowedToBeMigratedOltDictionary;
547: var imsServiceToRouterVendorDictionary = Ia.Ngn.Cl.Model.Data.Service.ImsServiceToOntAndMsanRouterVendorInAllowedToBeMigratedOltAndDomainDictionary;
548:
549: var ewsdSubscriberProvisionedServiceList = Ia.Ngn.Cl.Model.Data.Siemens.Subscriber.ProvisionedServiceList();
550:
551: // intersect lists
552: var list0 = ewsdSubscriberProvisionedServiceList.Intersect(imsServiceToRouterVendorDictionary.Keys).ToList();
553:
554: // will exclude exempt numbers
555: var serviceExemptionList = Ia.Ngn.Cl.Model.Data.Provision.ServiceOfServiceExemptFromProvisionProcessingList();
556:
557: var list = list0.Except(serviceExemptionList).ToList();
558:
559: foreach (string service in list)
560: {
561: var pstn = Ia.Ngn.Cl.Model.Data.NetworkDesignDocument.PstnFromService(service);
562:
563: // delete
564: provisioningWorkflowList.Add(new ProvisioningWorkflow
565: {
566: Service = service,
567: Pstn = pstn,
568: DeleteCommand = DeleteServiceCommand(pstn, service)
569: });
570:
571: // read
572: provisioningWorkflowList.Add(provisioningWorkflow = new ProvisioningWorkflow
573: {
574: Service = service,
575: Pstn = pstn,
576: ReadCommand = ReadServiceCommand(pstn, service),
577: });
578: }
579:
580: return provisioningWorkflowList;
581: }
582:
583: ////////////////////////////////////////////////////////////////////////////
584:
585: /// <summary>
586: ///
587: /// </summary>
588: public static ProvisioningWorkflow SynchronizeBetweenServiceRequestAdministrativeIssueAndSiemensEwsdPstnServiceProvisioningWorkflowItem()
589: {
590: ProvisioningWorkflow provisioningWorkflow;
591: List<ProvisioningWorkflow> list;
592:
593: provisioningWorkflow = null;
594:
595: if (serviceSuspentionSynchronizationProvisioningWorkflowQueue.Count == 0)
596: {
597: list = Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ServiceSuspentionAndReadCommandSynchronizeBetweenServiceRequestAdministrativeIssueAndSiemensEwsdPstnServiceProvisioningWorkflowList();
598:
599: serviceSuspentionSynchronizationProvisioningWorkflowQueue = new Queue<ProvisioningWorkflow>(list); // don't shuffle because a modify command is followed by a read .Shuffle());
600: }
601:
602: if (serviceSuspentionSynchronizationProvisioningWorkflowQueue.Count > 0) provisioningWorkflow = serviceSuspentionSynchronizationProvisioningWorkflowQueue.Dequeue();
603:
604: return provisioningWorkflow;
605: }
606:
607: ////////////////////////////////////////////////////////////////////////////
608:
609: /// <summary>
610: ///
611: /// </summary>
612: public static List<ProvisioningWorkflow> ServiceSuspentionAndReadCommandSynchronizeBetweenServiceRequestAdministrativeIssueAndSiemensEwsdPstnServiceProvisioningWorkflowList()
613: {
614: bool serviceSuspensionState;
615: ProvisioningWorkflow provisioningWorkflow;
616: List<ProvisioningWorkflow> provisioningWorkflowList;
617:
618: provisioningWorkflowList = new List<ProvisioningWorkflow>();
619:
620: Ia.Ngn.Cl.Model.Data.Provision.SiemensEwsdPstnServiceSuspensionMismatchBetweenServiceRequestAdministrativeIssueAndServiceServiceList(out List<string> serviceToSuspendList, out List<string> serviceToReleaseList, out _, out _);
621:
622: // will exclude exempt numbers
623: var serviceExemptionList = Ia.Ngn.Cl.Model.Data.Provision.ServiceOfServiceExemptFromProvisionProcessingList();
624:
625: serviceSuspensionState = true;
626:
627: foreach (var service in serviceToSuspendList)
628: {
629: if (!serviceExemptionList.Contains(service))
630: {
631: var pstn = Ia.Ngn.Cl.Model.Data.NetworkDesignDocument.PstnFromService(service);
632:
633: provisioningWorkflowList.Add(new ProvisioningWorkflow
634: {
635: Service = service,
636: Pstn = pstn,
637: ServiceSuspensionCommand = ServiceSuspensionCommand(pstn, service, serviceSuspensionState),
638: });
639:
640: provisioningWorkflowList.Add(new ProvisioningWorkflow
641: {
642: Service = service,
643: Pstn = pstn,
644: ReadCommand = ReadServiceCommand(pstn, service)
645: });
646: }
647: }
648:
649:
650: serviceSuspensionState = false;
651:
652: foreach (var service in serviceToReleaseList)
653: {
654: if (!serviceExemptionList.Contains(service))
655: {
656: var pstn = Ia.Ngn.Cl.Model.Data.NetworkDesignDocument.PstnFromService(service);
657:
658: provisioningWorkflowList.Add(new ProvisioningWorkflow
659: {
660: Service = service,
661: Pstn = pstn,
662: ServiceSuspensionCommand = ServiceSuspensionCommand(pstn, service, serviceSuspensionState),
663: });
664:
665: provisioningWorkflowList.Add(new ProvisioningWorkflow
666: {
667: Service = service,
668: Pstn = pstn,
669: ReadCommand = ReadServiceCommand(pstn, service)
670: });
671: }
672: }
673:
674: return provisioningWorkflowList;
675: }
676:
677: ////////////////////////////////////////////////////////////////////////////
678:
679: /// <summary>
680: ///
681: /// </summary>
682: public static Ia.Ngn.Cl.Model.Business.Service.ServiceSupplementaryService ServiceSupplementaryServiceStateFromServiceNetManagerOutputString(string content)
683: {
684: string matchedText, line;
685: Match m;
686: Ia.Ngn.Cl.Model.Business.Service.ServiceSupplementaryService serviceSupplementaryService;
687:
688: serviceSupplementaryService = new Ia.Ngn.Cl.Model.Business.Service.ServiceSupplementaryService();
689:
690: /*
691: ******************************************************************************************************
692: Sample Subscriber Information:
693:
694: QRN/QRN/KUWCPK1V5140P047/106 19-06-26 10:39:40
695: 3324 NetM ROMMEL07 2816/03800
696:
697: DISPSUB:DN=25421113;
698:
699: MASKNO:03800
700: LAC = 01 DN = 25421113 EQN = 20- 2-12-14
701: CAT = MS MASKNO:03774
702: OPTRCL = 2 MASKNO:03798
703: SUBTRCL = 2
704: NUMCAL = 1 MASKNO:08641
705: ORIG1 = 5
706: TRARSTR = TRACLACT MASKNO:03803
707: LNATT = PB MASKNO:03787
708: COS = CLIP FSK MASKNO:03777
709: ADDINF = KEYWORD MASKNO:03772
710:
711: END JOB 3324
712:
713:
714: ******************************************************************************************************
715:
716: OPTRCL = 2 ---> WITHOUT INTERNATIONAL CALL ENTERED BY OPERATOR
717: OPTRCL = 0 ---> WITH INTERNATIONAL CALL ENTERED BY OPERATOR
718:
719: SUBTRCL = 2 ---> WITHOUT INTERNATIONAL CALL MODIFIED BY SUBSCRIBER
720: SUBTRCL = 0 ---> WITH INTERNATIONAL CALL MODIFIED BY SUBSCRIBER
721:
722: TRARSTR = ACTTRACL TRACLACT ---> TRAFFIC RESTRATION FEATURES IS ACTIVATED (SUBSCRIBER CAN OPEN AND CLOSE INTERNATIONAL CALL)
723:
724: DIV = DIVI DIVIMOD DDVIN ---> DIVERSATION IMMIDIATE FEATURES IS ASSIGNED TO SUBSCRIBER
725: DIV = ACTDIVI -9793XXXX ---> SUBSCRIBER IMMEDIATELY DIVERTED TO GIVEN NUMBER
726:
727: COS = ACTCW ---> CALL WAITING FEATURE ACTIVATED
728: COS = CWACT ---> CALL WAITING ACTIVATION/DEACTIVATION VIA SUBSCRIBER CONTROL INPUT
729: COS = CONF3 ---> 3 PARTY CALLFERENCING FEATURE ACTIVATED
730: COS = PROP8 ---> ALARM CALL SERVICE FEATURE IS ACTIVATED
731: COS = CLIP FSK ---> CALLER ID FEATURES IS ACTIVATED
732:
733: ADDINF = KEYWORD ---> SUBSCRIBER HAS PIN
734: NOTE: TO CHECK THE SUBSCRIBER PIN (PASSWORD) THE COMMAND IS
735: DISPKEYWORD:DN=25421113;
736:
737: BLK = ACCSUSP ---> SUBSCRIBER ACCOUNT SUSPENDED NOT PAYING THE BILL
738: BLK = ADMIN ---> SUBSCRIBER ACCOUNT SUSPENDED NOT PAYING THE BILL
739: BLK = ADMIN1, ADMIN2, ADMIN3 ---> SUBSCRIBER ACCOUNT SUSPENDED OTHER REASON
740: */
741:
742:
743: /*
744: 2019-12-26 06:07:42: ServiceSymbolList: Service symbol list: CAT = MS, LTT = COSLAC2, OPTRCL = 2, SU
745: BTRCL = 2, NUMCAL = 1, ORIG1 = 5, DIV = DIVI DIVIMOD DDVIN, BLK = ACCSUSP, TRARSTR = ACTTRACL TRACLA
746: CT, LNATT = PB, COS = ACTCW CONF3 CWACT PROP8 CLIP, OPTRCL = 0, BLK = ACCSUSP ADMIN1, ADDINF = KEYWO
747: RD, COS = CLIP FSK, TRARSTR = TRACLACT, COS = CONF3 CWACT PROP8 CLIP FSK, DIV = ACTDIVI -22255408, C
748: OS = ACTCW CWACT, DIV = ACTDIVI -1885050, DIV = ACTDIVI -98542783, SUBTRCL = 5, DIV = ACTDIVI -23630
749: 149, DIV = ACTDIVI -97140405, DIV = ACTDIVI -98765061, LTT = COSLAC1, DIV = ACTDIVI -56660104, TRARS
750: TR = REQSPORI REQSPTER, DIV = ACTDIVI -96608155, DIV = ACTDIVI -90070130, DIV = ACTDIVI -50867570, D
751: IV = ACTDIVI -99066818, BLK = ADMIN1, COS = ACTCW CWACT CLIP FSK, DIV = ACTDIVI -55157777, DIV = ACT
752: DIVI -22255407, DIV = ACTDIVI -60361542, DIV = ACTDIVI -23832042, BLK = ADMIN2, DIV = ACTDIVI -22255
753: 406, DIV = ACTDIVI -97718256, DIV = ACTDIVI -25430752, DIV = ACTDIVI -23847000, DIV = ACTDIVI -94130
754: 075, DIV = ACTDIVI -90070140, DIV = ACTDIVI -98941899, DIV = ACTDIVI -66165244, DIV = ACTDIVI -99000
755: 064, DIV = ACTDIVI -99392712, DIV = ACTDIVI -99583218, DIV = ACTDIVI -90061187, TRARSTR = ACTTRACL T
756: RACLACT TRACLMOD, DIV = ACTDIVI -66667641, DIV = ACTDIVI -99326080, DIV = ACTDIVI -55865281, DIV = A
757: CTDIVI -94171955, DIV = ACTDIVI -22255495, DIV = DIVI -5610, COS = ACTCW CONF3 CWACT CLIP FSK, DIV =
758: ACTDIVI -50955607, DIV = ACTDIVI -22255496
759: */
760:
761: m = Regex.Match(content, @"DISPSUB:DN=(\d{8});");
762:
763: if (m.Success)
764: {
765: matchedText = m.Groups[1].Value;
766:
767: if (int.TryParse(matchedText, out int dn))
768: {
769: serviceSupplementaryService.Service = dn;
770:
771: using (StringReader reader = new StringReader(content))
772: {
773: while ((line = reader.ReadLine()) != null)
774: {
775: // COS = CLIP FSK ---> CALLER ID FEATURES IS ACTIVATED
776: m = Regex.Match(line, @"COS.+CLIP.+FSK");
777: if (m.Success) serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.CallerId);
778:
779: // COS = ACTCW ---> CALL WAITING FEATURE ACTIVATED
780: m = Regex.Match(line, @"COS.+ACTCW");
781: if (m.Success) serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.CallWaiting);
782:
783: // COS = CWACT ---> CALL WAITING ACTIVATION/DEACTIVATION VIA SUBSCRIBER CONTROL INPUT
784: m = Regex.Match(line, @"COS.+CWACT");
785: if (m.Success) serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.CallWaiting);
786:
787: // COS = CONF3 ---> 3 PARTY CALLFERENCING FEATURE ACTIVATED
788: m = Regex.Match(line, @"COS.+CONF3");
789: if (m.Success) serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.ConferenceCall);
790:
791: // COS = PROP8 ---> ALARM CALL SERVICE FEATURE IS ACTIVATED
792: m = Regex.Match(line, @"COS.+PROP8");
793: if (m.Success) serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.WakeupCall);
794:
795: // DIV = DIVI DIVIMOD DDVIN ---> DIVERSATION IMMIDIATE FEATURES IS ASSIGNED TO SUBSCRIBER
796: m = Regex.Match(line, @"DIV.+DIVI.+DIVIMOD.+DDVIN");
797: if (m.Success) serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.CallForwarding);
798:
799: // DIV = ACTDIVI -9793XXXX ---> SUBSCRIBER IMMEDIATELY DIVERTED TO GIVEN NUMBER
800: m = Regex.Match(line, @"DIV\s+=.+ACTDIVI.+-(\d{8})");
801: if (m.Success) serviceSupplementaryService.Pin = m.Value;
802:
803: // OPTRCL = 0 ---> WITH INTERNATIONAL CALL ENTERED BY OPERATOR
804: // OPTRCL = 2 ---> WITHOUT INTERNATIONAL CALL ENTERED BY OPERATOR
805: m = Regex.Match(line, @"OPTRCL\s+=\s+0");
806: if (m.Success) serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.InternationalCalling);
807:
808: // TRARSTR = ACTTRACL TRACLACT ---> TRAFFIC RESTRATION FEATURES IS ACTIVATED (SUBSCRIBER CAN OPEN AND CLOSE INTERNATIONAL CALL)
809: m = Regex.Match(line, @"TRARSTR.+ACTTRACL.+TRACLACT");
810: if (m.Success) serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.InternationalCallingUserControlled);
811:
812: // SUBTRCL = 0 ---> WITH INTERNATIONAL CALL MODIFIED BY SUBSCRIBER
813: // SUBTRCL = 2 ---> WITHOUT INTERNATIONAL CALL MODIFIED BY SUBSCRIBER
814: m = Regex.Match(line, @"SUBTRCL\s+=\s+0");
815: if (m.Success) serviceSupplementaryService.InternationalCallingUserControlledActivated = true;
816:
817: // BLK = ACCSUSP ---> SUBSCRIBER ACCOUNT SUSPENDED NOT PAYING THE BILL
818: // BLK = ADMIN ---> SUBSCRIBER ACCOUNT SUSPENDED NOT PAYING THE BILL
819: // BLK = ADMIN1, ADMIN2, ADMIN3 ---> SUBSCRIBER ACCOUNT SUSPENDED OTHER REASON
820: m = Regex.Match(line, @"BLK\s+=.+[ACCSUSP|ADMIN]");
821: if (m.Success)
822: {
823: serviceSupplementaryService.ServiceAdministrativelySuspendedByBillingDepartment = true;
824: serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.ServiceSuspension);
825: }
826: m = Regex.Match(line, @"BLK\s+=.+[ADMIN1|ADMIN2|ADMIN3]");
827: if (m.Success)
828: {
829: serviceSupplementaryService.ServiceAdministrativelySuspendedForOtherReasons = true;
830: serviceSupplementaryService.SupplementaryServiceList.Add(Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.ServiceSuspension);
831: }
832:
833: // ADDINF = KEYWORD ---> SUBSCRIBER HAS PIN
834: m = Regex.Match(line, @"ADDINF\s+=.+KEYWORD");
835: if (m.Success) serviceSupplementaryService.SubscriberHasPin = true;
836: }
837: }
838:
839: Ia.Ngn.Cl.Model.Business.Siemens.Ewsd.ExtractAndUpdateUniqueEwsdServiceSymbolListFromOutputContent(content);
840: }
841: else
842: {
843: }
844: }
845: else
846: {
847: }
848:
849: return serviceSupplementaryService;
850: }
851:
852: ////////////////////////////////////////////////////////////////////////////
853: ////////////////////////////////////////////////////////////////////////////
854:
855: /// <summary>
856: ///
857: /// </summary>
858: public static string ReadServiceCommand(Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pstn pstn, string service)
859: {
860: return EwsdCommand(Opcode.Dispsub, service); // + "\r\n" + EwsdCommand(Opcode.Dispkeyword, service) + "\r\n";
861: }
862:
863: /*
864: ////////////////////////////////////////////////////////////////////////////
865:
866: /// <summary>
867: ///
868: /// </summary>
869: public static string RouteServiceCommand(Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pstn pstn, string service)
870: {
871: string s;
872:
873: if (!pstn.UsesNpServer) s = EwsdCommand(Opcode.Crcpt, service) + "\r\n";
874: else s = string.Empty;
875:
876: return s;
877: }
878: */
879:
880: ////////////////////////////////////////////////////////////////////////////
881:
882: /// <summary>
883: ///
884: /// </summary>
885: public static string DeleteServiceCommand(Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pstn pstn, string service)
886: {
887: string s;
888:
889: /*if (!pstn.UsesNpServer)*/
890: s = EwsdCommand(Opcode.Cansub, service) + "\r\n";
891: //else s = string.Empty;
892:
893: return s;
894: }
895:
896: ////////////////////////////////////////////////////////////////////////////
897:
898: /// <summary>
899: ///
900: /// </summary>
901: public static string UpdateSupplementaryServiceCommand(string service, Ia.Ngn.Cl.Model.Business.Service.SupplementaryService supplementaryService, bool supplementaryServiceState)
902: {
903: string dn;
904: string command;
905:
906: dn = service;
907:
908: switch (supplementaryService)
909: {
910: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.AbbriviatedCalling):
911: {
912: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
913: break;
914: }
915: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.CallerId):
916: {
917: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
918: break;
919: }
920: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.CallForwarding):
921: {
922: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
923: break;
924: }
925: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.CallWaiting):
926: {
927: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
928: break;
929: }
930: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.ConferenceCall):
931: {
932: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
933: break;
934: }
935: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.WakeupCall):
936: {
937: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
938: break;
939: }
940: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.InternationalCallingUserControlled):
941: {
942: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
943: break;
944: }
945: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.InternationalCalling):
946: {
947: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
948: break;
949: }
950: case (Ia.Ngn.Cl.Model.Business.Service.SupplementaryService.ServiceSuspension):
951: {
952: command = EwsdCommand(Opcode.UpdateSubXxx, dn);
953: break;
954: }
955: default:
956: {
957: command = dn + ",unknown SupplementaryService: " + supplementaryServiceState.ToString().ToLower();
958: break;
959: }
960: }
961:
962: return command;
963: }
964:
965: ////////////////////////////////////////////////////////////////////////////
966:
967: /// <summary>
968: ///
969: /// </summary>
970: public static string ServiceSuspensionCommand(Ia.Ngn.Cl.Model.Business.NetworkDesignDocument.Pstn pstn, string service, bool serviceSuspensionState)
971: {
972: string command;
973:
974: /*if (!pstn.UsesNpServer)*/
975: if (serviceSuspensionState) command = EwsdCommand(Opcode.SuspendTemp, service, true) + "\r\n"; // suspend
976: else command = EwsdCommand(Opcode.SuspendTemp, service, false) + "\r\n"; // release
977: //else s = string.Empty;
978:
979: return command;
980: }
981:
982: ////////////////////////////////////////////////////////////////////////////
983: ////////////////////////////////////////////////////////////////////////////
984:
985: /// <summary>
986: ///
987: /// </summary>
988: public static string EwsdCommand(Opcode opcode, string dn)
989: {
990: string command;
991:
992: if (opcode == Opcode.Dispsub) command = "DISPSUB:DN=" + dn + ";";
993: else if (opcode == Opcode.Dispkeyword) command = "DISPKEYWORD:DN=" + dn + ";";
994: else if (opcode == Opcode.Cansub) command = "CANSUB:DN=" + dn + ";";
995: else if (opcode == Opcode.UpdateSubXxx) command = "DISPSUB:DN=" + dn + ";";
996: //else if (opcode == Opcode.Crcpt) command = "CRCPT:CODE=" + dn + ",DEST=QRNTOHUAWEI,ORIG1=DEF;";
997: //else if (opcode == Opcode.Disptime) command = "DISPTIME;";
998: else
999: {
1000: throw new System.ArgumentOutOfRangeException("EwsdCommand(): Opcode unrecognized. ");
1001: }
1002:
1003: return command;
1004: }
1005:
1006: ////////////////////////////////////////////////////////////////////////////
1007:
1008: /// <summary>
1009: ///
1010: /// </summary>
1011: public static string EwsdCommand(Opcode opcode, string dn, bool b)
1012: {
1013: string command;
1014:
1015: if (opcode == Opcode.SuspendTemp) command = "SuspendTemp:DN=" + dn + ",Temp=" + b + ";";
1016: else if (opcode == Opcode.UpdateSubXxx) command = "DISPSUB:DN=" + dn + ";";
1017: else
1018: {
1019: throw new System.ArgumentOutOfRangeException("EwsdCommand(): Opcode unrecognized. ");
1020: }
1021:
1022: return command;
1023: }
1024:
1025: ////////////////////////////////////////////////////////////////////////////
1026:
1027: /// <summary>
1028: /// Extract unique EWSD service symbols into array
1029: /// </summary>
1030: public static void ExtractAndUpdateUniqueEwsdServiceSymbolListFromOutputContent(string outputContent)
1031: {
1032: string s;
1033: MatchCollection matchCollection;
1034:
1035: matchCollection = Regex.Matches(outputContent, @"\r\n [\w]{1,}\s+= .+[^\r\n]");
1036:
1037: if (matchCollection.Count > 0)
1038: {
1039: foreach (Match match in matchCollection)
1040: {
1041: s = Regex.Replace(match.Value, @"MASKNO:\d+", "");
1042: s = Regex.Replace(s, @"\s+", " ");
1043: s = s.Trim();
1044:
1045: if (!ServiceSymbolList.Contains(s))
1046: {
1047: ServiceSymbolList.Add(s);
1048: }
1049: }
1050: }
1051: }
1052:
1053: ////////////////////////////////////////////////////////////////////////////
1054: ////////////////////////////////////////////////////////////////////////////
1055:
1056: /// <summary>
1057: ///
1058: /// </summary>
1059: public static string SpecialHandlingAndModificationOfPstnName(string pstnName)
1060: {
1061: // change JBL, SSB, FHH to QRN because they are just RSUs following QRN
1062: string modifiedPstnName;
1063:
1064: if (pstnName == "JBL") modifiedPstnName = "QRN";
1065: //else if (pstnName == "SSB") modifiedPstnName = "QRN"; // SSB is decommissioned
1066: else if (pstnName == "FHH") modifiedPstnName = "QRN";
1067: else if (pstnName == "WAF") modifiedPstnName = "QRN";
1068: else if (pstnName == "ZOR") modifiedPstnName = "QRN";
1069: else if (pstnName == "AMD") modifiedPstnName = "QRN";
1070: else if (pstnName == "RKK") modifiedPstnName = "QRN";
1071: else if (pstnName == "SHB") modifiedPstnName = "QRN";
1072: else if (pstnName == "UHN") modifiedPstnName = "QRN";
1073: else if (pstnName == "ABD") modifiedPstnName = "TECB";
1074: else modifiedPstnName = pstnName;
1075:
1076: return modifiedPstnName;
1077: }
1078:
1079: ////////////////////////////////////////////////////////////////////////////
1080: ////////////////////////////////////////////////////////////////////////////
1081: }
1082: }
1083: