b9e2b53f3d9a64691f9f57a36d2e265b6f0058dd
[appc/cdt.git] / src / app / shared / services / mapping-editor.service.ts
1 /*
2 ============LICENSE_START==========================================
3 ===================================================================
4 Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
5 ===================================================================
6
7 Unless otherwise specified, all software contained herein is licensed
8 under the Apache License, Version 2.0 (the License);
9 you may not use this software except in compliance with the License.
10 You may obtain a copy of the License at
11
12     http://www.apache.org/licenses/LICENSE-2.0
13
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19
20 ============LICENSE_END============================================
21 */
22
23
24 import {Injectable} from '@angular/core';
25 import {ConfigMapping} from '../models/index';
26 import {Observable} from 'rxjs/Observable';
27 import {Observer} from 'rxjs/Observer';
28 import 'rxjs/add/operator/share';
29
30
31 @Injectable()
32 export class MappingEditorService {
33
34     editor: any;
35     session: any;
36     editorContent: string;
37     configMappings: Array<ConfigMapping> = [];
38     paramContent: string = '{}';
39
40     KEY_EXPRESSION: string = '\\${\\(.+?\\)}';//new RegExp('${.+?}'); // \${.+?}
41     KEY_START: string = '${(';
42     KEY_MID: string = ')=(';
43     KEY_END: string = ')}';
44     KEY_START_LENGTH: number = 3;
45     KEY_MID_LENGTH: number = 3;
46     KEY_END_LENGTH: number = 2;
47     SYNC_T_KEY_EXPRESSION: string = '\\${.+?\\}';
48     T_KEY_EXPRESSION: string = '\\${.+?}';//new RegExp('${.+?}'); // \${.+?}
49     T_KEY_START: string = '${';
50     T_KEY_END: string = '}';
51     T_KEY_START_LENGTH: number = 2;
52     T_KEY_END_LENGTH: number = 1;
53     checkSpecialCharsReg: RegExp = /[^\w\s-_]/gi;
54     public paramData = [];
55     public referenceNameObjects: any;
56     prmName: string = '';
57     prmValue: string = '';
58     navChange$: Observable<any>;
59     public fromScreen: any = '';
60     public storedTemplateData: any;
61     public storedTemplateMappingData: any;
62     public fileType: any;
63     public hasErrorCode: boolean = false;
64     public appDataObject: any;
65     public downloadDataObject: any;
66     public markedarr: any;
67     public tempAllData: any;
68     public latestAction: any;
69     public selectedWord: any;
70     identifier: any;
71     private _navItem = {};
72     private _observer: Observer<any>;
73     private referenceList = [];
74     newObject: any;
75
76     constructor() {
77         this.navChange$ = new Observable(observer =>
78             this._observer = observer).share();
79     }
80
81     setSelectedWord(selectedWord: any) {
82         this.selectedWord = selectedWord;
83     }
84
85     getSelectedWord() {
86         return this.selectedWord;
87     }
88
89     changeNav(object) {
90         this._navItem = object;
91         this.referenceNameObjects = object;
92     }
93
94     changeNavAppData(object) {
95         this._navItem = object;
96         this.appDataObject = object;
97     }
98
99     changeNavDownloadData(object) {
100         this._navItem = object;
101         this.downloadDataObject = object;
102     }
103
104     saveLatestAction(data) {
105         this.latestAction = data;
106     }
107     selectedObj(data) {
108         this.newObject = data;
109     }
110
111     saveLatestIdentifier(identifier) {
112         this.identifier = identifier;
113     }
114
115     public getParamContent() {
116         return this.paramContent;
117     }
118
119     saveTempAllData(data) {
120         this.tempAllData = data;
121     }
122
123     navItem() {
124         return this._navItem;
125     }
126
127     public setParamContent(paramContent: string): void {
128         this.paramContent = paramContent;
129         
130     }
131
132     public initialise(editor: any, editorContent: string, modal: any): void {
133         this.editor = editor;
134         this.editor.session = editor.session;
135         this.editor.selection.session.$backMarkers = {};
136         this.editorContent = editorContent;
137         this.editor.$blockScrolling = Infinity;
138         this.editor.$blockSelectEnabled = false;
139         this.initialiseCommands(modal);
140         this.editor.setValue(this.editorContent);
141         this.refreshEditor();
142     }
143
144
145     public initialiseCommands(modal): void {
146         this.editor.commands.addCommand({
147             name: 'keyCompletionCommand',
148             bindKey: {win: 'Ctrl-s', mac: 'Command-s'},
149             exec: (editor: any) => {
150                 this.handlekeyCompletion();
151             }
152         });
153
154         this.editor.commands.addCommand({
155             name: 'autoAnnotateCommand',
156             bindKey: {win: 'Ctrl-2', mac: 'Command-2'},
157             exec: (editor: any) => {
158                 this.autoAnnotateDataForParams();
159             }
160         });
161
162         this.editor.commands.addCommand({
163             name: 'autoAnnotateCommand',
164             bindKey: {win: 'Ctrl-shift-z', mac: 'Command-shift-z'},
165             exec: (editor: any) => {
166                 this.removeTheSelectedMarkers();
167             }
168         });
169     }
170
171     public getStartBeforeAfterSelection(selection: any, beforeCount: number, afterCount: number) {
172         let newSelctionRange: any = JSON.parse(JSON.stringify(selection));
173         if (selection) {
174             let newBeforeColumn: number = selection.start.column - beforeCount;
175             let newAfterColumn: number = selection.end.column + afterCount;
176             newSelctionRange.start.column = newBeforeColumn;
177             newSelctionRange.end.column = newAfterColumn;
178         }
179         return newSelctionRange;
180     }
181
182     public checkToDataAdd(value: string): boolean {
183         let toAdd = false;
184         if (value && (value.startsWith('"') || value.startsWith('>'))
185             && (value.endsWith('"') || value.endsWith('<'))
186             && !value.startsWith('"${')
187         ) {
188             toAdd = true;
189         }
190         return toAdd;
191     }
192
193     public autoAnnotateDataForParams(): boolean {
194         this.paramContent = localStorage['paramsContent'];
195         var mergeStatus: boolean = false;
196         if (this.paramContent) {
197             var paramJson: JSON = JSON.parse(this.paramContent);
198             for (var prop in paramJson) {
199                 let value: string = paramJson[prop];
200                 if (value) {
201                     var occurances = this.editor.findAll(value, {regExp: false});
202                     var ranges = this.editor.getSelection().getAllRanges();
203                     if (ranges && occurances && occurances > 0) {
204
205                         for (var r = 0; r < ranges.length; r++) {
206                             let selectedRange: any = ranges[r];
207                             let selectedWord: string = this.editor.session.getTextRange(selectedRange);
208                             let prefixSuffixselectedWord: string = this.editor.session.getTextRange(this.getStartBeforeAfterSelection(selectedRange, 1, 1));
209                             if (selectedWord && this.checkComments(selectedRange) && this.checkDelimiters(selectedRange) && this.checkApplied(selectedRange)) {
210                                 let replaceWord: any = this.KEY_START + selectedWord + this.KEY_MID + prop + this.KEY_END;
211                                 this.editor.session.replace(selectedRange, replaceWord);
212                                 mergeStatus = true;
213                             }
214                         }
215                     }
216                 }
217             }
218         }
219         return mergeStatus;
220     }
221
222     checkComments(selectedRange: any) {
223         var tempStartColumn = selectedRange.start.column;
224         var result = false;
225         selectedRange.start.column = 0;
226         if (this.editor.session.getTextRange(selectedRange).trim().startsWith('//')) {
227             result = false;
228         } else {
229             result = true;
230         }
231         selectedRange.start.column = tempStartColumn;
232         return result;
233     }
234
235     checkApplied(selectedRange: any) {
236         var tempStartColumn = selectedRange.start.column;
237         for (var i = selectedRange.start.column; i >= 0; i--) {
238             selectedRange.start.column = i;
239             if (this.editor.session.getTextRange(selectedRange).startsWith(this.KEY_START)
240                 || this.editor.session.getTextRange(selectedRange).startsWith(this.T_KEY_START)) {
241                 selectedRange.start.column = tempStartColumn;
242                 return false;
243             } else if (this.editor.session.getTextRange(selectedRange).startsWith(this.KEY_END)
244                 || this.editor.session.getTextRange(selectedRange).startsWith(this.T_KEY_END)) {
245                 selectedRange.start.column = tempStartColumn;
246                 return true;
247             }
248
249         }
250         selectedRange.start.column = tempStartColumn;
251         return true;
252
253     }
254
255     checkDelimiters(selectedRange: any) {
256         let result = false;
257         let actualText = this.editor.session.getTextRange(selectedRange);
258         var tempStartColumn = selectedRange.start.column;
259         var tempEndcolumn = selectedRange.end.column;
260
261         selectedRange.start.column = selectedRange.start.column - 1;
262         selectedRange.end.column = selectedRange.end.column + 1;
263         if ((this.editor.session.getTextRange(selectedRange).startsWith(' ')
264                 || this.editor.session.getTextRange(selectedRange).startsWith('"')
265                 || this.editor.session.getTextRange(selectedRange).startsWith('>'))
266             && (this.editor.session.getTextRange(selectedRange).endsWith(' ')
267                 || this.editor.session.getTextRange(selectedRange).endsWith('"')
268                 || this.editor.session.getTextRange(selectedRange).endsWith(',')
269                 || this.editor.session.getTextRange(selectedRange).endsWith(actualText)
270                 || this.editor.session.getTextRange(selectedRange).endsWith('<'))) {
271             result = true;
272         }
273
274         //Ignore the JSON key names(which ends with :)
275         selectedRange.end.column = selectedRange.end.column + 1;
276         if (this.editor.session.getTextRange(selectedRange).endsWith('":')) {
277             result = false;
278         } else {
279             selectedRange.end.column = selectedRange.end.column + 1;
280             if (this.editor.session.getTextRange(selectedRange).endsWith('" :')) {
281                 result = false;
282             }
283         }
284         selectedRange.start.column = tempStartColumn;
285         selectedRange.end.column = tempEndcolumn;
286         return result;
287     }
288
289     checkAppliedForNamesOnly(selectedRange: any) {
290         var tempStartColumn = selectedRange.start.column;
291         for (var i = selectedRange.start.column; i >= 0; i--) {
292             selectedRange.start.column = i;
293             if (this.editor.session.getTextRange(selectedRange).startsWith(this.KEY_START)) {
294                 selectedRange.start.column = tempStartColumn;
295                 return false;
296             } else if (this.editor.session.getTextRange(selectedRange).startsWith(this.KEY_END)) {
297                 selectedRange.start.column = tempStartColumn;
298                 return true;
299             }
300
301         }
302         selectedRange.start.column = tempStartColumn;
303         return true;
304
305     }
306
307     checkToDataAddForJson(value: string): boolean {
308         let toAdd = false;
309         if (value && !value.startsWith('"${') && !value.startsWith('(')) {
310             toAdd = true;
311         }
312         return toAdd;
313     }
314
315     public autoAnnotateTemplateForParam(): void {
316         var occurances = this.editor.findAll(this.T_KEY_EXPRESSION, {regExp: true});
317         var ranges = this.editor.getSelection().getAllRanges();
318         if (ranges) {
319             for (var r = 0; r < ranges.length; r++) {
320                 let selectedRange: any = ranges[r];
321                 let selectedWord: string = this.editor.session.getTextRange(selectedRange);
322                 if (selectedWord) {
323                     let key: string = selectedWord.substring(this.T_KEY_START_LENGTH, selectedWord.lastIndexOf(this.T_KEY_END));
324                     let value: string = this.getValueForKey(key);
325                     let replaceWord: any = this.KEY_START + value + this.KEY_MID + key + this.KEY_END;
326                     this.editor.session.replace(selectedRange, replaceWord);
327                 }
328             }
329         }
330
331     }
332
333     /*
334      * Once you save command is triggered, We need to re populate all the params, which may be defined new
335      * and auto populate the key if any of the values maps to the keys
336      */
337     public handlekeyCompletion(): void {
338         this.refreshEditor();
339     }
340
341     public checkMethodCall(modal): void {
342     //this.handleAnnotation(modal)
343     }
344
345     public refreshEditor(): void {
346         if (this.editor) {
347
348             var occurances = this.editor.findAll(this.KEY_EXPRESSION, {regExp: true});
349             var ranges = this.editor.getSelection().getAllRanges();
350             if (ranges) {
351                 this.refreshParams(ranges);
352             }
353
354             occurances = this.editor.findAll(this.KEY_EXPRESSION, {regExp: true});
355             ranges = this.editor.getSelection().getAllRanges();
356             if (ranges) {
357                 this.populateMissingKeys(ranges);
358             }
359             this.refreshMarker();
360         }
361         
362     }
363
364     replaceNamesWithBlankValues() {
365         var occurances = this.editor.findAll(this.SYNC_T_KEY_EXPRESSION, {regExp: true});
366         var ranges = this.editor.getSelection().getAllRanges();
367         if (occurances > 0) {
368             if (ranges) {
369                 for (var r = 0; r < ranges.length; r++) {
370                     let selectedRange: any = ranges[r];
371                     let selectedWord: string = this.editor.session.getTextRange(selectedRange);
372                     let specialKeys = (selectedWord.substring(2, selectedWord.length - 1)).match(this.checkSpecialCharsReg);
373                     if (selectedWord && this.checkAppliedForNamesOnly(selectedRange) && !specialKeys) {
374                         let replaceWord: any = this.KEY_START + '' + this.KEY_MID + selectedWord.substring(2, selectedWord.length - 1) + this.KEY_END;
375                         this.editor.session.replace(selectedRange, replaceWord);
376                     }
377                    
378                 }
379             }
380         }
381     }
382
383     public refreshParams(ranges: any): void {
384         var paramData = [];
385         if (this.paramContent === undefined) this.paramContent = '{}';
386         if (this.editor && ranges) {
387             var paramJson: JSON = JSON.parse(this.paramContent);
388             this.hasErrorCode = false;
389             for (var r = 0; r < ranges.length; r++) {
390                 let keyValue: string = this.editor.session.getTextRange(ranges[r]);
391                 if (keyValue && keyValue.startsWith(this.KEY_START) && keyValue.endsWith(this.KEY_END) && keyValue.includes(this.KEY_MID)) {
392                     let key: string = keyValue.substring(keyValue.indexOf(this.KEY_MID) + this.KEY_MID_LENGTH, keyValue.indexOf(this.KEY_END));
393                     let value: string = keyValue.substring(this.KEY_START_LENGTH, keyValue.indexOf(this.KEY_MID));
394                     let specialKeys = key.match(this.checkSpecialCharsReg);
395                     if (specialKeys && specialKeys.length) {
396                       
397                     } else {
398                         if (this.fromScreen === 'TemplateScreen') {
399                             if (key) {
400                                 paramJson[key] = value;
401                                 var obj: any = {'paramName': '', 'paramValue': ''};
402                                 obj.paramName = key;
403                                 obj.paramValue = value;
404                                 paramData.push(obj);
405                             }
406
407                         }
408                         else if (this.fromScreen === 'MappingScreen') {
409                             if (key) {
410                                 paramJson[key] = value;
411                                 var obj: any = {'paramName': '', 'paramValue': ''};
412                                 obj.paramName = key;
413                                 obj.paramValue = value;
414
415                                 paramData.push(obj);
416
417                             }
418                         }
419                     }
420                 }
421             }
422             this.paramData = paramData;
423             this.paramContent = JSON.stringify(paramJson);
424
425         }
426     }
427
428     public populateMissingKeys(ranges: any): void {
429         if (this.editor && ranges) {
430             // Populate missing keys
431             for (var r = 0; r < ranges.length; r++) {
432                 let keyValue: string = this.editor.session.getTextRange(ranges[r]);
433                 if (keyValue && keyValue.startsWith(this.KEY_START) && keyValue.endsWith(this.KEY_END) && keyValue.includes(this.KEY_MID)) {
434                     let key: string = keyValue.substring(keyValue.indexOf(this.KEY_MID) + this.KEY_MID_LENGTH, keyValue.indexOf(this.KEY_END));
435                     let value: string = keyValue.substring(this.KEY_START_LENGTH, keyValue.indexOf(this.KEY_MID));
436                     if (!key && value) {
437                         let keyFromStore = '';
438                         if (keyFromStore) {
439                             let replaceWord: string = '${(' + value + ')=(' + keyFromStore + ')}';
440                             this.editor.session.replace(ranges[r], replaceWord);
441                         }
442                     }
443                 }
444             }
445
446         }
447     }
448
449     public refreshMarker(): void {
450         if (this.editor) {
451             this.hasErrorCode = false;
452             var occurances = this.editor.findAll(this.KEY_EXPRESSION, {regExp: true});
453             var ranges = this.editor.getSelection().getAllRanges();
454             var keysList = [];
455             // Populate missing keys
456             for (var r = 0; r < ranges.length; r++) {
457                 let keyValue: string = this.editor.session.getTextRange(ranges[r]);
458                 if (keyValue && keyValue.startsWith(this.KEY_START) && keyValue.endsWith(this.KEY_END) && keyValue.includes(this.KEY_MID)) {
459                     let key: string = keyValue.substring(keyValue.indexOf(this.KEY_MID) + this.KEY_MID_LENGTH, keyValue.indexOf(this.KEY_END));
460                     let value: string = keyValue.substring(this.KEY_START_LENGTH, keyValue.indexOf(this.KEY_MID));
461                     let specialKeys = key.match(this.checkSpecialCharsReg);
462                     if (specialKeys && specialKeys.length) {
463                         this.hasErrorCode = true;
464                         break;
465                     }
466                     if (!key && value) {
467                         this.editor.session.addMarker(ranges[r], 'warningMarker', 'text');
468                     } else {
469                         if (keysList.indexOf(key) > -1) {
470                             this.editor.session.addMarker(ranges[r], 'warningMarker', 'text');
471                         } else {
472                             this.editor.session.addMarker(ranges[r], 'keyedMarker', 'text');
473                         }
474                         keysList.push(key);
475                     }
476                     // Refresh Markers
477                 }
478             }
479             this.editor.clearSelection();
480             this.editor.exitMultiSelectMode();
481         }
482     }
483
484     public getKeysForValues(value: string): string {
485         var key: string = undefined;
486         if (this.paramContent && value) {
487             var paramJson: JSON = JSON.parse(this.paramContent);
488             for (var prop in paramJson) {
489                 if (value === paramJson[prop]) {
490                     key = prop;
491                 }
492             }
493         }
494         return key;
495     }
496
497     public getValueForKey(key: string): string {
498         var value: string = undefined;
499         if (key) {
500             var paramJson: JSON = JSON.parse(this.paramContent);
501             if (paramJson) {
502                 value = paramJson[key];
503             }
504         }
505         return value;
506     }
507
508     public generateTemplate(templateEditor: any): void {
509         if (templateEditor) {
510             templateEditor.setValue(this.editor.getValue());
511             var occurances = templateEditor.findAll(this.KEY_EXPRESSION, {regExp: true});
512             var ranges = templateEditor.getSelection().getAllRanges();
513             if (ranges) {
514                 for (var r = 0; r < ranges.length; r++) {
515                     let keyValue: string = templateEditor.session.getTextRange(ranges[r]);
516                     if (keyValue && keyValue.startsWith(this.KEY_START) && keyValue.endsWith(this.KEY_END) && keyValue.includes(this.KEY_MID)) {
517                         let key: string = keyValue.substring(keyValue.indexOf(this.KEY_MID) + this.KEY_MID_LENGTH, keyValue.indexOf(this.KEY_END));
518                         let value: string = keyValue.substring(this.KEY_START_LENGTH, keyValue.indexOf(this.KEY_MID));
519                         if (key && value) {
520                             let replaceWord: string = '${' + key + '}';
521                             templateEditor.session.replace(ranges[r], replaceWord);
522                         }
523                     }
524                 }
525                 templateEditor.clearSelection();
526                 templateEditor.exitMultiSelectMode();
527                 templateEditor.session.$backMarkers = {};
528
529             }
530         }
531     }
532
533     public generateParams(paramsEditor: any, paramsKeyValueEditor: any): JSON {
534         if (paramsEditor && paramsKeyValueEditor) {
535             var occurances = this.editor.findAll(this.KEY_EXPRESSION, {regExp: true});
536             var ranges = this.editor.getSelection().getAllRanges();
537             if (ranges) {
538                 let paramsJSON: JSON = JSON.parse('{}');
539                 for (var r = 0; r < ranges.length; r++) {
540                     let keyValue: string = this.editor.session.getTextRange(ranges[r]);
541                     if (keyValue && keyValue.startsWith(this.KEY_START) && keyValue.endsWith(this.KEY_END) && keyValue.includes(this.KEY_MID)) {
542                         let key: string = keyValue.substring(keyValue.indexOf(this.KEY_MID) + this.KEY_MID_LENGTH, keyValue.indexOf(this.KEY_END));
543                         let value: string = keyValue.substring(this.KEY_START_LENGTH, keyValue.indexOf(this.KEY_MID));
544                         if (key) {
545                             paramsJSON[key] = value;
546                         }
547                     }
548                 }
549
550                 var propertyContent = [];
551                 for (var prop in paramsJSON) {
552                     propertyContent.push(prop + '=' + paramsJSON[prop]);
553                 }
554                 this.editor.clearSelection();
555                 this.editor.exitMultiSelectMode();
556                 return paramsJSON;
557             }
558         }
559     }
560
561     setTemplateDataForStore(templateData: any) {
562         this.storedTemplateData = templateData;
563     }
564
565     getTemplateDataFromStore() {
566         return this.storedTemplateData;
567     }
568
569     removeTheSelectedMarkers() {
570         var arr: any = [];
571         arr = this.markedarr;
572         this.editor.selection.session.$backMarkers = {};
573     }
574
575     getsaveMarkers() {
576         this.markedarr = [...this.editor.selection.session.$selectionMarkers];
577     }
578
579     getTemplateMappingDataFromStore() {
580         return this.storedTemplateMappingData;
581     }
582
583     setTemplateMappingDataFromStore(templateMappingData: any) {
584         this.storedTemplateMappingData = templateMappingData;
585     }
586
587     public setReferenceList(references) {
588         this.referenceList = references;
589     }
590
591     public getReferenceList() {
592         return this.referenceList;
593     }
594
595
596 }