/
BaseDAO.ts
172 lines (152 loc) · 4.86 KB
/
BaseDAO.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import {IHasHTTP} from '../api/IHasHTTP';
import {IOnmsHTTP} from '../api/IOnmsHTTP';
import {OnmsError} from '../api/OnmsError';
import {OnmsServer} from '../api/OnmsServer';
import {log} from '../api/Log';
/** @hidden */
// tslint:disable-next-line
const moment = require('moment');
/** @hidden */
// tslint:disable-next-line
import {Moment} from 'moment';
import { Util } from '../internal/Util';
/**
* A base DAO useful for subclassing to create real DAOs. This differs from
* the [[AbstractDAO]] in that it doesn't have a "default" interface for
* dealing with model objects, it only provides core conveniences.
*
* @category DAO
*/
export abstract class BaseDAO {
/**
* The [[IOnmsHTTP]] implementation to use internally when making DAO requests.
* @hidden
*/
private httpImpl: IOnmsHTTP;
/**
* The [[OnmsServer]] that was last updated/retrieved. This is used to check whether caches
* need to be invalidated.
* @hidden
* @param serverImpl The last [[OnmsServer]] seen.
*/
private serverImpl?: OnmsServer | null;
/**
* Construct a DAO instance.
*
* @param impl - The HTTP implementation to use. It is also legal to pass any object
* conforming to the [[IHasHTTP]] interface (like a [[Client]]).
*/
constructor(impl: IOnmsHTTP | IHasHTTP) {
if ((impl as IHasHTTP).http) {
impl = (impl as IHasHTTP).http;
}
this.httpImpl = impl as IOnmsHTTP;
this.serverImpl = this.httpImpl.server;
}
/**
* The HTTP implementation to use internally when making DAO requests.
*/
public get http() {
this.validateServer();
return this.httpImpl;
}
public set http(impl: IOnmsHTTP) {
this.httpImpl = impl;
}
/**
* The [[OnmsServer]] being connected to by this DAO.
*/
public get server(): OnmsServer {
this.validateServer();
if (this.serverImpl) {
return this.serverImpl;
}
throw new OnmsError('No server configured!');
}
public set server(s: OnmsServer) {
this.httpImpl.server = s;
this.serverImpl = s;
this.onSetServer(s || undefined);
}
/**
* Called whenever accessing the HTTP impl or server to validate whether it has changed.
* @hidden
*/
protected validateServer() {
if (this.serverImpl) {
// we have a cached server, evaluate if it is still correct
if (this.httpImpl) {
// we have both a locally set server and a server in the HTTP implementation
if (this.serverImpl.equals(this.httpImpl.server || undefined)) {
// if they match, we're fine
return;
} else {
// if not, cache the HTTP impl version locally and call `onSetServer`
this.serverImpl = this.httpImpl.server;
this.onSetServer(this.serverImpl || undefined);
}
} else {
// HTTP impl server has become unset or HTTP impl has changed, set server impl to undefined
this.serverImpl = null;
this.onSetServer(this.serverImpl || undefined);
}
} else {
// no server impl set, if there's an HTTP impl, sync with its server, otherwise just set to undefined
if (this.httpImpl) {
this.serverImpl = this.httpImpl.server;
this.onSetServer(this.serverImpl || undefined);
}
}
}
/**
* Called whenever the OpenNMS server has changed.
* @param server the new server
*/
protected onSetServer(server?: OnmsServer) {
// this should be overridden by implementations
}
/**
* Whether or not to use JSON when making ReST requests.
*/
protected useJson(): boolean {
if (!this.server || this.server.metadata === null) {
throw new OnmsError('Server meta-data must be populated prior to making DAO calls.');
}
return this.server.metadata.useJson();
}
/**
* A convenience method to make it easy for implementers to extract the count
* (or totalCount) values from response data.
*/
protected getCount(data: any, status?: number): number {
let count = 0;
if (typeof(data) === 'number') {
count = data;
} else if (data.count !== undefined) {
count = parseInt(data.count, 10);
} else if (data.totalCount !== undefined) {
count = parseInt(data.totalCount, 10);
} else {
if (status === 204) {
log.debug('data is missing count and totalCount properties');
} else {
log.warn('data is missing count and totalCount properties, but HTTP status was not 204');
}
}
return count;
}
/**
* Convert the given value to a date, or undefined if it cannot be converted.
* @deprecated use {@link Util.toDate} instead.
*/
protected toDate(from: any): Moment|undefined {
return Util.toDate(from);
}
/**
* Convert the given value to a number, or undefined if it cannot be converted.
* @deprecated use {@link Util.toNumber} instead.
*/
protected toNumber(from: any): number|undefined {
return Util.toNumber(from);
}
}