blob: 9636bb2a7bbec04cdefbcb0cc3439abb9a88d49b [file] [log] [blame]
Matteo Scandolo968e7f22017-03-03 11:49:18 -08001import * as _ from 'lodash';
Matteo Scandoloa62adbc2017-03-02 15:37:34 -08002import {Observable, BehaviorSubject} from 'rxjs';
3import {IXosModelStoreService} from '../../datasources/stores/model.store';
Matteo Scandolo968e7f22017-03-03 11:49:18 -08004import {
5 IXosServiceGraph, IXosServiceModel, IXosTenantModel, IXosCoarseGraphData,
6 IXosServiceGraphNode, IXosServiceGraphLink
7} from '../interfaces';
Matteo Scandoloa62adbc2017-03-02 15:37:34 -08008import {IXosDebouncer} from '../../core/services/helpers/debounce.helper';
9export interface IXosServiceGraphStore {
10 get(): Observable<IXosServiceGraph>;
Matteo Scandolo968e7f22017-03-03 11:49:18 -080011 getCoarse(): Observable<IXosServiceGraph>;
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080012}
13
14export class XosServiceGraphStore implements IXosServiceGraphStore {
15 static $inject = [
16 '$log',
17 'XosModelStore',
18 'XosDebouncer'
19 ];
Matteo Scandolo968e7f22017-03-03 11:49:18 -080020
21 // graph data store
22 private graphData: BehaviorSubject<IXosCoarseGraphData> = new BehaviorSubject({
23 services: [],
24 tenants: []
25 });
26
27 // reprentations of the graph as D3 requires
28 private d3CoarseGraph = new BehaviorSubject({});
29 private d3FineGrainedGraph = new BehaviorSubject({});
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080030
31 // storing locally reference to the data model
32 private services;
33 private tenants;
34
35 // debounced functions
36 private handleData;
37
38 // datastore
39 private ServiceObservable: Observable<any>;
40 private TenantObservable: Observable<any>;
41
42 constructor (
43 private $log: ng.ILogService,
44 private XosModelStore: IXosModelStoreService,
45 private XosDebouncer: IXosDebouncer
46 ) {
47
Matteo Scandolo968e7f22017-03-03 11:49:18 -080048 this.$log.info(`[XosServiceGraphStore] Setup`);
49
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080050 // we want to have a quiet period of 500ms from the last event before doing anything
Matteo Scandolo968e7f22017-03-03 11:49:18 -080051 this.handleData = this.XosDebouncer.debounce(this._handleData, 500, this, false);
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080052
53 this.ServiceObservable = this.XosModelStore.query('Service', '/core/services');
Matteo Scandolo968e7f22017-03-03 11:49:18 -080054 this.TenantObservable = this.XosModelStore.query('Tenant', '/core/tenants');
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080055
Matteo Scandolo968e7f22017-03-03 11:49:18 -080056 // observe models and populate graphData
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080057 this.ServiceObservable
58 .subscribe(
59 (res) => {
60 this.combineData(res, 'services');
61 },
62 (err) => {
63 this.$log.error(err);
64 }
65 );
66
Matteo Scandolo968e7f22017-03-03 11:49:18 -080067 this.TenantObservable
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080068 .subscribe(
69 (res) => {
70 this.combineData(res, 'tenants');
71 },
72 (err) => {
73 this.$log.error(err);
74 }
75 );
Matteo Scandolo968e7f22017-03-03 11:49:18 -080076
77 // observe graphData and build Coarse or FineGrained graphs (based on who's subscribed)
78 this.graphData
79 .subscribe(
80 (res: IXosCoarseGraphData) => {
81 if (this.d3CoarseGraph.observers.length > 0) {
82 this.graphDataToCoarseGraph(res);
83 }
84 if (this.d3FineGrainedGraph.observers.length > 0) {
85 // TODO graphDataToFineGrainedGraph
86 }
87 },
88 (err) => {
89 this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
90 }
91 );
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080092 }
93
94 public get() {
Matteo Scandolo968e7f22017-03-03 11:49:18 -080095 return this.d3FineGrainedGraph.asObservable();
96 }
97
98 public getCoarse() {
99 return this.d3CoarseGraph.asObservable();
Matteo Scandoloa62adbc2017-03-02 15:37:34 -0800100 }
101
102 private combineData(data: any, type: 'services'|'tenants') {
103 switch (type) {
104 case 'services':
105 this.services = data;
106 break;
107 case 'tenants':
108 this.tenants = data;
109 break;
110 }
111 this.handleData(this.services, this.tenants);
112 }
113
114 private _handleData(services: IXosServiceModel[], tenants: IXosTenantModel[]) {
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800115 this.graphData.next({
116 services: this.services,
117 tenants: this.tenants
118 });
119 }
120
Matteo Scandolo0c61c9b2017-03-03 11:49:18 -0800121 private getNodeIndexById(id: number, nodes: IXosServiceModel[]) {
122 return _.findIndex(nodes, {id: id});
123 }
124
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800125 private graphDataToCoarseGraph(data: IXosCoarseGraphData) {
126
Matteo Scandolo0c61c9b2017-03-03 11:49:18 -0800127 // TODO find how to bind source/target by node ID and not by position in array (ask Simon?)
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800128 const links: IXosServiceGraphLink[] = _.chain(data.tenants)
129 .filter((t: IXosTenantModel) => t.kind === 'coarse')
130 .map((t: IXosTenantModel) => {
131 return {
132 id: t.id,
Matteo Scandolo0c61c9b2017-03-03 11:49:18 -0800133 source: this.getNodeIndexById(t.provider_service_id, data.services),
134 target: this.getNodeIndexById(t.subscriber_service_id, data.services),
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800135 model: t
136 };
137 })
138 .value();
139
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800140 const nodes: IXosServiceGraphNode[] = _.map(data.services, (s: IXosServiceModel) => {
141 return {
142 id: s.id,
143 label: s.name,
144 model: s
145 };
146 });
147
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800148 this.d3CoarseGraph.next({
149 nodes: nodes,
150 links: links
151 });
Matteo Scandoloa62adbc2017-03-02 15:37:34 -0800152 }
153
154}