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