UNPKG

opennms

Version:

Client API for the OpenNMS network monitoring platform

221 lines (198 loc) 7.67 kB
import {IFilterProcessor} from '../api/IFilterProcessor'; import {IHasHTTP} from '../api/IHasHTTP'; import {IOnmsHTTP} from '../api/IOnmsHTTP'; import {OnmsError} from '../api/OnmsError'; import {Filter} from '../api/Filter'; import {OnmsHTTPOptions} from '../api/OnmsHTTPOptions'; import {SearchProperty} from '../api/SearchProperty'; import {SearchPropertyType} from '../api/SearchPropertyType'; import {log, catDao} from '../api/Log'; import {V1FilterProcessor} from './V1FilterProcessor'; import {V2FilterProcessor} from './V2FilterProcessor'; import {PropertiesCache} from './PropertiesCache'; import {BaseDAO} from './BaseDAO'; /** @hidden */ // tslint:disable-next-line const moment = require('moment'); /** @hidden */ // tslint:disable-next-line import {Moment} from 'moment'; import {IValueProvider} from './IValueProvider'; /** * An abstract data access layer API, meant to (somewhat) mirror the DAO interfaces * inside OpenNMS. Used to retrieve model data like alarms, events, etc. from the * OpenNMS ReST API in a consistent way. * * @module AbstractDAO * @param K the ID/key type (number, string, etc.) * @param T the model type (OnmsAlarm, OnmsEvent, etc.) */ export abstract class AbstractDAO<K, T> extends BaseDAO implements IValueProvider { /** * Returns the Promise for a [[IFilterProcessor]]. * @returns {Promise} */ public async getFilterProcessor(): Promise<IFilterProcessor> { switch (this.getApiVersion()) { case 2: return this.getPropertiesCache().then((cache) => { return new V2FilterProcessor(cache); }); default: return Promise.resolve(new V1FilterProcessor()); } } /** * Retrieve a model object. * @param id - the ID of the object */ public abstract async get(id: K): Promise<T>; /** * Find all model objects given an optional filter. * @param filter - the filter to use when retrieving a list of model objects */ public abstract async find(filter?: Filter): Promise<T[]>; /** * Get the list properties that can be used in queries. * @version ReST v2 */ public async searchProperties(): Promise<SearchProperty[]> { return this.getPropertiesCache().then((cache) => { return cache.getProperties(); }); } /** * Gets the property identified by the id if it exists. * * @param id The id to search the property by. */ public async searchProperty(id: string): Promise<SearchProperty> { return this.getPropertiesCache().then((cache) => { return cache.getProperty(id); }); } /** * Returns or creates the [[PropertiesCache]] for this dao. * * @return the [[PropertiesCache]] for this dao. It is created if it does not exist. */ public async getPropertiesCache(): Promise<PropertiesCache> { if (this.getApiVersion() === 1) { throw new OnmsError('Search property metadata is only available in OpenNMS ' + 'versions that support the ReSTv2 API.'); } // Cache not yet initialized if (!PropertiesCache.get(this)) { return this.getOptions().then((opts) => { opts.headers.accept = 'application/json'; return this.http.get(this.searchPropertyPath(), opts).then((result) => { const searchProperties = this.parseResultList(result, 'searchProperty', this.searchPropertyPath(), (prop) => { return this.toSearchProperty(prop); }); PropertiesCache.put(this, searchProperties); return Promise.resolve(PropertiesCache.get(this)); }); }); } // Cache already initialized, use value return Promise.resolve(PropertiesCache.get(this)); } /** * Finds the values for the given propertyId, if it exists. * * @param {string} propertyId The propertyId to find the values for * @param options Some additional options. May be implementer dependent, such as limit, or value restrictions * @returns {Promise<any>} A promise containing the values. */ public async findValues(propertyId: string, options?: any): Promise<any> { return this.searchProperty(propertyId).then((property) => { return this.getOptions().then((opts) => { const path = this.searchPropertyPath() + '/' + property.id; opts.headers.accept = 'application/json'; if (options) { Object.assign(opts, options); } return this.http.get(path, opts).then((result) => { return this.parseResultList(result, 'value', path, (value) => value); }); }); }); } /** * The path to retrieve search properties for this DAO. */ protected abstract searchPropertyPath(): string; /** * Fetches the data from the result and verfifes that the <code>dataFieldName</code> exists in the data property. * If it does not exist, an exception is thrown. * * @param result The result to fetch the data from * @param dataFieldName The property name (basically <code>result.data[dataFieldName]</code>. * @param path The path where the result was fetched from. This is for error handling * @param mapCallbackFunction Callback function to convert each entry from <code>result.data[dataFieldName]</code>. */ protected parseResultList(result: any, dataFieldName: string, path: string, mapCallbackFunction: any): any { let data = result.data; if (this.getCount(data) > 0 && data[dataFieldName]) { data = data[dataFieldName]; } else { data = []; } if (!Array.isArray(data)) { throw new OnmsError('Expected an array but got "' + (typeof data) + '" instead: ' + path); } if (mapCallbackFunction) { return data.map(mapCallbackFunction); } return data; } /** * Create an [[OnmsHTTPOptions]] object for DAO calls given an optional filter. * @param filter - the filter to use */ protected async getOptions(filter?: Filter): Promise<OnmsHTTPOptions> { return Promise.resolve(new OnmsHTTPOptions()) .then((options) => { if (this.useJson()) { options.headers.accept = 'application/json'; } else { // always use application/xml in DAO calls when we're not sure how // usable JSON output will be. options.headers.accept = 'application/xml'; } if (filter) { return this.getFilterProcessor().then((processor) => { options.parameters = processor.getParameters(filter); return options; }); } return options; }); } /** * Generate a [[SearchProperty]] from the given dictionary. * @hidden */ protected toSearchProperty(data: any): SearchProperty { if (!data) { return null; } const prop = new SearchProperty(this); prop.id = data.id; prop.name = data.name; prop.orderBy = !!data.orderBy; prop.type = SearchPropertyType.forId(data.type); prop.values = data.values; return prop; } /** * Retrieve the API version from the currently configured server. */ protected getApiVersion(): number { if (this.http === undefined || this.http.server === undefined || this.http.server.metadata === undefined) { throw new OnmsError('Server meta-data must be populated prior to making DAO calls.'); } return this.http.server.metadata.apiVersion(); } }