You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by sa...@apache.org on 2019/07/15 11:41:30 UTC
[metron] branch feature/METRON-1856-parser-aggregation updated:
METRON-2115 [UI] Aligning UI to the parser aggregation API (tiborm via
sardell) closes apache/metron#1414
This is an automated email from the ASF dual-hosted git repository.
sardell pushed a commit to branch feature/METRON-1856-parser-aggregation
in repository https://gitbox.apache.org/repos/asf/metron.git
The following commit(s) were added to refs/heads/feature/METRON-1856-parser-aggregation by this push:
new 130f97f METRON-2115 [UI] Aligning UI to the parser aggregation API (tiborm via sardell) closes apache/metron#1414
130f97f is described below
commit 130f97f39e7b9e223e8a431ceec1b45096bd38fa
Author: tiborm <ti...@gmail.com>
AuthorDate: Mon Jul 15 13:40:42 2019 +0200
METRON-2115 [UI] Aligning UI to the parser aggregation API (tiborm via sardell) closes apache/metron#1414
---
...sensor-parser-config-readonly.component.spec.ts | 4 +-
.../sensor-parser-config-readonly.component.ts | 2 +-
.../sensor-parser-config-history.service.spec.ts | 8 +-
.../service/sensor-parser-config.service.spec.ts | 374 ++++++++++++++++++++-
.../app/service/sensor-parser-config.service.ts | 172 ++++++++--
5 files changed, 513 insertions(+), 47 deletions(-)
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts
index 16628d1..4ebfb6d 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts
+++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.spec.ts
@@ -645,7 +645,7 @@ describe('Component: SensorParserConfigReadonly', () => {
it('onDeleteSensor should delete the sensor', async(() => {
spyOn(
sensorParserConfigService,
- 'deleteSensorParserConfig'
+ 'deleteConfig'
).and.returnValue(
Observable.create(observer => {
observer.next({});
@@ -662,7 +662,7 @@ describe('Component: SensorParserConfigReadonly', () => {
component.onDeleteSensor();
expect(
- sensorParserConfigService.deleteSensorParserConfig
+ sensorParserConfigService.deleteConfig
).toHaveBeenCalledWith('abc');
expect(alerts.showSuccessMessage).toHaveBeenCalledWith(
'Deleted sensor abc'
diff --git a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts
index bbc04f4..04c8c69 100644
--- a/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts
+++ b/metron-interface/metron-config/src/app/sensors/sensor-parser-config-readonly/sensor-parser-config-readonly.component.ts
@@ -444,7 +444,7 @@ export class SensorParserConfigReadonlyComponent implements OnInit {
this.toggleStartStopInProgress();
let name = this.selectedSensorName;
- this.sensorParserConfigService.deleteSensorParserConfig(name).subscribe(
+ this.sensorParserConfigService.deleteConfig(name).subscribe(
result => {
this.metronAlerts.showSuccessMessage('Deleted sensor ' + name);
this.toggleStartStopInProgress();
diff --git a/metron-interface/metron-config/src/app/service/sensor-parser-config-history.service.spec.ts b/metron-interface/metron-config/src/app/service/sensor-parser-config-history.service.spec.ts
index 4816ae5..ae7de24 100644
--- a/metron-interface/metron-config/src/app/service/sensor-parser-config-history.service.spec.ts
+++ b/metron-interface/metron-config/src/app/service/sensor-parser-config-history.service.spec.ts
@@ -16,15 +16,15 @@
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
-import { SensorParserConfig } from '../model/sensor-parser-config';
+import { ParserConfigModel } from '../sensors/models/parser-config.model';
import { SensorParserConfigHistoryService } from './sensor-parser-config-history.service';
import { SensorParserConfigHistory } from '../model/sensor-parser-config-history';
import {
HttpTestingController,
HttpClientTestingModule
} from '@angular/common/http/testing';
-import {AppConfigService} from './app-config.service';
-import {MockAppConfigService} from './mock.app-config.service';
+import { AppConfigService } from './app-config.service';
+import { MockAppConfigService } from './mock.app-config.service';
describe('SensorParserConfigHistoryService', () => {
let mockBackend: HttpTestingController;
@@ -50,7 +50,7 @@ describe('SensorParserConfigHistoryService', () => {
describe('when service functions', () => {
let sensorParserConfigHistory = new SensorParserConfigHistory();
- sensorParserConfigHistory.config = new SensorParserConfig();
+ sensorParserConfigHistory.config = new ParserConfigModel('TestConfigId01');
it('get', () => {
sensorParserConfigHistoryService.get('bro').subscribe(
diff --git a/metron-interface/metron-config/src/app/service/sensor-parser-config.service.spec.ts b/metron-interface/metron-config/src/app/service/sensor-parser-config.service.spec.ts
index 6e63113..b138017 100644
--- a/metron-interface/metron-config/src/app/service/sensor-parser-config.service.spec.ts
+++ b/metron-interface/metron-config/src/app/service/sensor-parser-config.service.spec.ts
@@ -67,7 +67,7 @@ describe('SensorParserConfigService', () => {
it('post', () => {
sensorParserConfigService
- .post('bro', sensorParserConfig)
+ .saveConfig('bro', sensorParserConfig)
.subscribe(result => {
expect(result).toEqual(sensorParserConfig);
});
@@ -78,7 +78,7 @@ describe('SensorParserConfigService', () => {
});
it('get', () => {
- sensorParserConfigService.get('bro').subscribe(result => {
+ sensorParserConfigService.getConfig('bro').subscribe(result => {
expect(result).toEqual(sensorParserConfig);
});
const req = mockBackend.expectOne('/api/v1/sensor/parser/config/bro');
@@ -87,7 +87,7 @@ describe('SensorParserConfigService', () => {
});
it('getAll', () => {
- sensorParserConfigService.getAll().subscribe(results => {
+ sensorParserConfigService.getAllConfig().subscribe(results => {
expect(results).toEqual([sensorParserConfig]);
});
const req = mockBackend.expectOne('/api/v1/sensor/parser/config');
@@ -122,7 +122,7 @@ describe('SensorParserConfigService', () => {
it('deleteSensorParserConfigs', () => {
let req = [];
sensorParserConfigService
- .deleteSensorParserConfigs(['bro1', 'bro2'])
+ .deleteConfigs(['bro1', 'bro2'])
.subscribe(result => {
expect(result.success.length).toEqual(2);
});
@@ -133,4 +133,370 @@ describe('SensorParserConfigService', () => {
r.flush(parsedMessage);
});
});
+
+ describe('REST Calls for Parser Grouping', () => {
+
+ it('getting list of parser groups', () => {
+ sensorParserConfigService.getAllGroups().subscribe((result: ParserGroupModel[]) => {
+ expect(result.length).toBe(2);
+ expect(result[0].name).toBe('TestGroupName1');
+ expect(result[0].description).toBe('TestDesc1');
+ });
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/group');
+ request.flush([
+ {
+ name: 'TestGroupName1',
+ description: 'TestDesc1'
+ },
+ {
+ name: 'TestGroupName2',
+ description: 'TestDesc2'
+ }
+ ]);
+ });
+
+ it('getting single parser group by name', () => {
+ sensorParserConfigService.getGroup('TestGroup').subscribe((result: ParserGroupModel) => {
+ expect(result.name).toBe('TestGroupName1');
+ expect(result.description).toBe('TestDesc1');
+ });
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup');
+ request.flush({
+ name: 'TestGroupName1',
+ description: 'TestDesc1'
+ });
+ });
+
+ it('creating/editing single parser group by name', () => {
+ sensorParserConfigService.saveGroup('TestGroup', new ParserGroupModel({
+ name: 'TestGroupName1',
+ description: 'TestDesc1',
+ sensors: ['foo']
+ })).subscribe();
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/group');
+ expect(request.request.method).toEqual('POST');
+ expect(request.request.body.name).toBe('TestGroupName1');
+ expect(request.request.body.description).toBe('TestDesc1');
+ expect(request.request.body.sensors).toEqual(['foo']);
+ });
+
+ it('deleting single parser group by name', () => {
+ sensorParserConfigService.deleteGroup('TestGroup').subscribe();
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup');
+ expect(request.request.method).toEqual('DELETE');
+ });
+
+ it('deleting multiple parser groups by name', () => {
+ sensorParserConfigService.deleteGroups(['TestGroup1', 'TestGroup2', 'TestGroup3'])
+ .subscribe((result) => {
+ expect(result.success.length).toBe(2);
+ expect(result.failure.length).toBe(1);
+ });
+
+ const request: Array<TestRequest> = [];
+ request.push(mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup1'));
+ request.push(mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup2'));
+ request.push(mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup3'));
+
+ expect(request[0].request.method).toEqual('DELETE');
+ expect(request[1].request.method).toEqual('DELETE');
+ expect(request[2].request.method).toEqual('DELETE');
+
+ request[0].flush({});
+ request[1].flush('Invalid request parameters', { status: 404, statusText: 'Bad Request' });
+ request[2].flush({});
+ });
+
+ function getTestGroups() {
+ return [
+ { config: new ParserGroupModel({ name: 'TestGroup01', description: '' }) },
+ { config: new ParserGroupModel({ name: 'TestGroup02', description: '' }) },
+ { config: new ParserGroupModel({ name: 'TestGroup03', description: '' }) },
+ { config: new ParserGroupModel({ name: 'TestGroup04', description: '' }) },
+ ];
+ }
+
+ function getTestConfigs() {
+ return [
+ { config: new ParserConfigModel('Parser_Config_ID_01', { sensorTopic: 'Kafka/Sensor Topic ID 01' }) },
+ { config: new ParserConfigModel('Parser_Config_ID_02', { sensorTopic: 'Kafka/Sensor Topic ID 02' }) },
+ { config: new ParserConfigModel('Parser_Config_ID_03', { sensorTopic: 'Kafka/Sensor Topic ID 03' }) },
+ { config: new ParserConfigModel('Parser_Config_ID_04', { sensorTopic: 'Kafka/Sensor Topic ID 04' }) },
+ ];
+ }
+
+ function markElementOnIndexAs(testData: ParserMetaInfoModel[], indexes: number[], flag: string) {
+ indexes.forEach((index) => {
+ testData[index][flag] = true;
+ })
+ }
+
+ class DirtyFlags {
+ static NEW = 'isPhantom';
+ static CHANGED = 'isDirty';
+ static DELETED = 'isDeleted';
+ }
+
+ it('syncronizing list of parser GROUPS with the backend - SINGLE DELETE', () => {
+ const testData = getTestGroups();
+
+ markElementOnIndexAs(testData, [1], DirtyFlags.DELETED);
+
+ sensorParserConfigService.syncGroups(testData).subscribe();
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup02');
+ expect(request.request.method).toEqual('DELETE');
+ });
+
+ it('syncronizing list of parser GROUPS with the backend - MULTIPLE DELETE', () => {
+ const testData = getTestGroups();
+
+ markElementOnIndexAs(testData, [0, 2, 3], DirtyFlags.DELETED);
+
+ sensorParserConfigService.syncGroups(testData).subscribe();
+
+ const requests = [];
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup01'));
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup04'));
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/group/TestGroup03'));
+ expect(requests[0].request.method).toEqual('DELETE');
+ expect(requests[1].request.method).toEqual('DELETE');
+ expect(requests[2].request.method).toEqual('DELETE');
+ });
+
+ it('syncronizing list of parser GROUPS with the backend - SINGLE NEW', () => {
+ const testData = getTestGroups();
+
+ markElementOnIndexAs(testData, [0], DirtyFlags.NEW);
+
+ sensorParserConfigService.syncGroups(testData).subscribe();
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/group');
+ expect(request.request.method).toEqual('POST');
+ expect(request.request.body.name).toEqual('TestGroup01');
+ expect(request.request.body.description).toEqual('');
+ });
+
+ it('syncronizing list of parser GROUPS with the backend - MULTIPLE NEW', () => {
+ const testData = getTestGroups();
+
+ markElementOnIndexAs(testData, [0, 2], DirtyFlags.NEW);
+
+ sensorParserConfigService.syncGroups(testData).subscribe();
+
+ const calls = mockBackend.match((request) => {
+ return request.url.match(/\/api\/v1\/sensor\/parser\/group/)
+ && request.method === 'POST';
+ });
+
+ expect(calls.length).toBe(2);
+ expect(calls[0].request.body.name).toEqual('TestGroup01');
+ expect(calls[1].request.body.name).toEqual('TestGroup03');
+ });
+
+ it('syncronizing list of parser GROUPS with the backend - SINGLE CHANGED', () => {
+ const testData = getTestGroups();
+
+ markElementOnIndexAs(testData, [3], DirtyFlags.CHANGED);
+
+ sensorParserConfigService.syncGroups(testData).subscribe();
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/group');
+ expect(request.request.method).toEqual('POST');
+ expect(request.request.body.name).toEqual('TestGroup04');
+ expect(request.request.body.description).toEqual('');
+ });
+
+ it('syncronizing list of parser GROUPS with the backend - MULTIPLE CHANGED', () => {
+ const testData = getTestGroups();
+
+ markElementOnIndexAs(testData, [0, 2], DirtyFlags.CHANGED);
+
+ sensorParserConfigService.syncGroups(testData).subscribe();
+
+ const calls = mockBackend.match(request => {
+ return request.url.match(/\/api\/v1\/sensor\/parser\/group/)
+ && request.method === 'POST';
+ });
+
+ expect(calls.length).toBe(2);
+ expect(calls[0].request.body.name).toEqual('TestGroup01');
+ expect(calls[1].request.body.name).toEqual('TestGroup03');
+ });
+
+ it('syncronizing list of PARSER CONFIGS with the backend - SINGLE DELETE', () => {
+ const testData = getTestConfigs();
+
+ markElementOnIndexAs(testData, [1], DirtyFlags.DELETED);
+
+ sensorParserConfigService.syncConfigs(testData).subscribe();
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_02');
+ expect(request.request.method).toEqual('DELETE');
+ });
+
+ it('syncronizing list of PARSER CONFIGS with the backend - MULTIPLE DELETE', () => {
+ const testData = getTestConfigs();
+
+ markElementOnIndexAs(testData, [0, 2, 3], DirtyFlags.DELETED);
+
+ sensorParserConfigService.syncConfigs(testData).subscribe();
+
+ const requests = [];
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_01'));
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_03'));
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_04'));
+ expect(requests[0].request.method).toEqual('DELETE');
+ expect(requests[1].request.method).toEqual('DELETE');
+ expect(requests[2].request.method).toEqual('DELETE');
+ });
+
+ it('syncronizing list of PARSER CONFIGS with the backend - SINGLE NEW', () => {
+ const testData = getTestConfigs();
+
+ markElementOnIndexAs(testData, [0], DirtyFlags.NEW);
+
+ sensorParserConfigService.syncConfigs(testData).subscribe();
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_01');
+ expect(request.request.method).toEqual('POST');
+ expect(JSON.parse(request.request.body).sensorTopic).toEqual('Kafka/Sensor Topic ID 01');
+ });
+
+ it('syncronizing list of PARSER CONFIGS with the backend - MULTIPLE NEW', () => {
+ const testData = getTestConfigs();
+
+ markElementOnIndexAs(testData, [0, 2], DirtyFlags.NEW);
+
+ sensorParserConfigService.syncConfigs(testData).subscribe();
+
+ const requests = [];
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_01'));
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_03'));
+ expect(requests[0].request.method).toEqual('POST');
+ expect(requests[1].request.method).toEqual('POST');
+
+ expect(JSON.parse(requests[0].request.body).sensorTopic).toEqual('Kafka/Sensor Topic ID 01');
+ expect(JSON.parse(requests[1].request.body).sensorTopic).toEqual('Kafka/Sensor Topic ID 03');
+ });
+
+ it('syncronizing list of PARSER CONFIGS with the backend - SINGLE CHANGED', () => {
+ const testData = getTestConfigs();
+
+ markElementOnIndexAs(testData, [3], DirtyFlags.CHANGED);
+
+ sensorParserConfigService.syncConfigs(testData).subscribe();
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_04');
+ expect(request.request.method).toEqual('POST');
+ expect(JSON.parse(request.request.body).sensorTopic).toEqual('Kafka/Sensor Topic ID 04');
+ });
+
+ it('syncronizing list of PARSER CONFIGS with the backend - MULTIPLE CHANGED', () => {
+ const testData = getTestConfigs();
+
+ markElementOnIndexAs(testData, [0, 2], DirtyFlags.CHANGED);
+
+ sensorParserConfigService.syncConfigs(testData).subscribe();
+
+ const requests = [];
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_01'));
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_03'));
+ expect(requests[0].request.method).toEqual('POST');
+ expect(requests[1].request.method).toEqual('POST');
+
+ expect(JSON.parse(requests[0].request.body).sensorTopic).toEqual('Kafka/Sensor Topic ID 01');
+ expect(JSON.parse(requests[1].request.body).sensorTopic).toEqual('Kafka/Sensor Topic ID 03');
+ });
+
+ it('syncronization of PARSER CONFIGS should return with an Observable array of successful/unsuccessful requests', () => {
+ const testData = getTestConfigs();
+
+ markElementOnIndexAs(testData, [0, 2], DirtyFlags.CHANGED);
+
+ sensorParserConfigService.syncConfigs(testData)
+ .subscribe((syncResults: any[]) => {
+ expect(syncResults.length === 2);
+ });
+
+ const requests = [];
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_01'));
+ requests.push(mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_03'));
+ requests[0].flush(requests[0].request.body);
+ requests[1].flush(requests[1].request.body);
+ });
+
+ it('error throwing in syncConfigs()', () => {
+ const testData = getTestConfigs();
+
+ markElementOnIndexAs(testData, [2], DirtyFlags.CHANGED);
+
+ sensorParserConfigService.syncConfigs(testData)
+ .subscribe(
+ noop,
+ (error) => {
+ expect(error).toBeDefined();
+ }
+ );
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/config/Parser_Config_ID_03');
+ request.flush('Invalid request parameters', { status: 404, statusText: 'Bad Request' });
+ });
+
+ it('error throwing in syncConfigs()', () => {
+ const testData = getTestGroups();
+
+ markElementOnIndexAs(testData, [1], DirtyFlags.CHANGED);
+
+ sensorParserConfigService.syncGroups(testData)
+ .subscribe(
+ noop,
+ (error) => {
+ expect(error).toBeDefined();
+ }
+ );
+
+ const request = mockBackend.expectOne('/api/v1/sensor/parser/group');
+ request.flush('Invalid request parameters', { status: 404, statusText: 'Bad Request' });
+ });
+
+ it('syncConfigs() should complete even if no changed item passed', () => {
+ const testData = getTestConfigs();
+
+ sensorParserConfigService.syncConfigs(testData)
+ .subscribe(
+ (value) => {
+ // we expect sync to return an empty array of result if no changed item
+ expect(value).toEqual([]);
+ },
+ noop,
+ () => {
+ // complete has to be called
+ expect(true).toBeTruthy();
+ }
+ );
+ });
+
+ it('syncGroups() should complete even if no changed item passed', () => {
+ const testData = getTestGroups();
+
+ sensorParserConfigService.syncGroups(testData)
+ .subscribe(
+ (value) => {
+ // we expect sync to return an empty array of result if no changed item
+ expect(value).toEqual([]);
+ },
+ noop,
+ () => {
+ // complete has to be called
+ expect(true).toBeTruthy();
+ }
+ );
+ });
+
+ })
});
diff --git a/metron-interface/metron-config/src/app/service/sensor-parser-config.service.ts b/metron-interface/metron-config/src/app/service/sensor-parser-config.service.ts
index add7cb5..7fb83a6 100644
--- a/metron-interface/metron-config/src/app/service/sensor-parser-config.service.ts
+++ b/metron-interface/metron-config/src/app/service/sensor-parser-config.service.ts
@@ -15,20 +15,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { Injectable, Inject } from '@angular/core';
+import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
-import { Observable, Subject } from 'rxjs';
-import { catchError, map } from 'rxjs/operators';
-import { SensorParserConfig } from '../model/sensor-parser-config';
+import { Observable, Subject, from, of } from 'rxjs';
+import { catchError, map, take, mergeMap, finalize, filter, reduce } from 'rxjs/operators';
+import { ParserConfigModel } from '../sensors/models/parser-config.model';
import { HttpUtil } from '../util/httpUtil';
import { ParseMessageRequest } from '../model/parse-message-request';
import { RestError } from '../model/rest-error';
-import {AppConfigService} from './app-config.service';
+import { ParserGroupModel } from '../sensors/models/parser-group.model';
+import { ParserModel } from 'app/sensors/models/parser.model';
+import { ParserMetaInfoModel } from '../sensors/models/parser-meta-info.model';
+import { AppConfigService } from './app-config.service';
@Injectable()
export class SensorParserConfigService {
- url = this.appConfigService.getApiRoot() + '/sensor/parser/config';
- selectedSensorParserConfig: SensorParserConfig;
dataChangedSource = new Subject<string[]>();
dataChanged$ = this.dataChangedSource.asObservable();
@@ -38,57 +39,140 @@ export class SensorParserConfigService {
private appConfigService: AppConfigService
) {}
- public post(
- name: string,
- sensorParserConfig: SensorParserConfig
- ): Observable<SensorParserConfig> {
- return this.http
- .post(this.url + '/' + name, JSON.stringify(sensorParserConfig))
- .pipe(
- map(HttpUtil.extractData),
- catchError(HttpUtil.handleError)
- );
+ private getParserConfigSvcUrl(): string {
+ return this.appConfigService.getApiRoot() + '/sensor/parser/config';
}
- public get(name: string): Observable<SensorParserConfig> {
- return this.http.get(this.url + '/' + name).pipe(
- map(HttpUtil.extractData),
+ private getParserGroupSvcUrl(): string {
+ return this.appConfigService.getApiRoot() + '/sensor/parser/group';
+ }
+
+ public getAllGroups(): Observable<ParserGroupModel[] | RestError> {
+ function extractParserGroups(raw) {
+ return Object.keys(raw).map((groupName) => {
+ return new ParserGroupModel({
+ ...raw[groupName]
+ })
+ });
+ }
+ return this.http.get(this.getParserGroupSvcUrl()).pipe(
+ map(extractParserGroups),
catchError(HttpUtil.handleError)
);
}
- public getAll(): Observable<{}> {
- return this.http.get(this.url).pipe(
+ public getGroup(name: string): Observable<RestError | ParserGroupModel> {
+ return this.http.get(`${this.getParserGroupSvcUrl()}/${name}`).pipe(
+ map(group => new ParserGroupModel(group)),
+ catchError(HttpUtil.handleError)
+ );
+ }
+
+ public saveGroup(name: string, group: ParserGroupModel | ParserModel): Observable<RestError | ParserGroupModel> {
+ return this.http.post(`${this.getParserGroupSvcUrl()}`, group).pipe(
map(HttpUtil.extractData),
catchError(HttpUtil.handleError)
);
}
- public deleteSensorParserConfig(
- name: string
- ): Observable<Object | RestError> {
- return this.http
- .delete(this.url + '/' + name)
- .pipe(catchError(HttpUtil.handleError));
+ public deleteGroup(groupName: string): Observable<{ groupName: string, isSuccess: boolean }> {
+ return this.http.delete(`${this.getParserGroupSvcUrl()}/${groupName}`).pipe(
+ map((result) => { return { groupName, isSuccess: true } }),
+ catchError((error) => { return of({ groupName, isSuccess: false }) })
+ );
}
- public getAvailableParsers(): Observable<{}> {
- return this.http.get(this.url + '/list/available').pipe(
+ public deleteGroups(
+ groupNames: string[]
+ ): Observable<{ success: Array<string>; failure: Array<string> }> {
+ let result: { success: Array<string>; failure: Array<string> } = {
+ success: [],
+ failure: []
+ };
+ let observable = Observable.create(observer => {
+ let completed = () => {
+ if (observer) {
+ observer.next(result);
+ observer.complete();
+ }
+ this.dataChangedSource.next(groupNames);
+ };
+ from(groupNames).pipe(
+ mergeMap(this.deleteGroup.bind(this)),
+ take(groupNames.length),
+ map((deleteResult: { groupName: string, isSuccess: boolean}) => {
+ (deleteResult.isSuccess ? result.success : result.failure).push(deleteResult.groupName);
+ }),
+ finalize(completed)
+ ).subscribe();
+ });
+
+ return observable;
+ }
+
+ syncConfigs(configs: ParserMetaInfoModel[]): Observable<{}> {
+ return this.sync(configs, this.saveConfig, this.deleteConfig);
+ }
+
+ syncGroups(groups: ParserMetaInfoModel[]): Observable<{}> {
+ return this.sync(groups, this.saveGroup, this.deleteGroup);
+ }
+
+ private sync(
+ items: ParserMetaInfoModel[],
+ saveFn: Function, deleteFn: Function
+ ) {
+ return from(items).pipe(
+ filter(item => !!(item.isDeleted || item.isDirty || item.isPhantom)),
+ mergeMap((changedItem: ParserMetaInfoModel) => {
+ if (changedItem.isDeleted) {
+ return deleteFn.call(this, changedItem.config.getName());
+ } else {
+ return saveFn.call(this, changedItem.config.getName(), changedItem.config);
+ }
+ }),
+ catchError(HttpUtil.handleError),
+ reduce((acc, value) => {
+ return acc.concat(value);
+ }, [])
+ )
+ }
+
+ public getConfig(name: string): Observable<ParserConfigModel> {
+ return this.http.get(this.getParserConfigSvcUrl() + '/' + name).pipe(
map(HttpUtil.extractData),
catchError(HttpUtil.handleError)
);
}
- public parseMessage(
- parseMessageRequest: ParseMessageRequest
- ): Observable<{}> {
- return this.http.post(this.url + '/parseMessage', parseMessageRequest).pipe(
+ public getAllConfig(): Observable<{}> {
+ return this.http.get(this.getParserConfigSvcUrl()).pipe(
map(HttpUtil.extractData),
catchError(HttpUtil.handleError)
);
}
- public deleteSensorParserConfigs(
+ public saveConfig(
+ name: string,
+ sensorParserConfig: ParserModel
+ ): Observable<ParserConfigModel> {
+ return this.http
+ .post(this.getParserConfigSvcUrl() + '/' + name, JSON.stringify(sensorParserConfig))
+ .pipe(
+ map(HttpUtil.extractData),
+ catchError(HttpUtil.handleError)
+ );
+ }
+
+ public deleteConfig(
+ name: string
+ ): Observable<Object | RestError> {
+ return this.http
+ .delete(this.getParserConfigSvcUrl() + '/' + name)
+ .pipe(catchError(HttpUtil.handleError));
+ }
+
+ public deleteConfigs(
sensorNames: string[]
): Observable<{ success: Array<string>; failure: Array<string> }> {
let result: { success: Array<string>; failure: Array<string> } = {
@@ -105,7 +189,7 @@ export class SensorParserConfigService {
this.dataChangedSource.next(sensorNames);
};
for (let i = 0; i < sensorNames.length; i++) {
- this.deleteSensorParserConfig(sensorNames[i]).subscribe(
+ this.deleteConfig(sensorNames[i]).subscribe(
results => {
result.success.push(sensorNames[i]);
if (
@@ -130,4 +214,20 @@ export class SensorParserConfigService {
return observable;
}
+
+ public getAvailableParsers(): Observable<{}> {
+ return this.http.get(this.getParserConfigSvcUrl() + '/list/available').pipe(
+ map(HttpUtil.extractData),
+ catchError(HttpUtil.handleError)
+ );
+ }
+
+ public parseMessage(
+ parseMessageRequest: ParseMessageRequest
+ ): Observable<{}> {
+ return this.http.post(this.getParserConfigSvcUrl() + '/parseMessage', parseMessageRequest).pipe(
+ map(HttpUtil.extractData),
+ catchError(HttpUtil.handleError)
+ );
+ }
}