Simon Hunt

GUI -- MapService: changed to cache promises with attached meta data.

- unit tests for cached promises still WIP.

Change-Id: Ibe52cf3e83ed5753ccc12581b52fa1f640354e60
......@@ -139,7 +139,7 @@
function register(viewBox, data, overwrite) {
var dmap = d3.map(data),
dups = [],
ok, msg;
ok;
dmap.forEach(function (key, value) {
if (!overwrite && glyphs.get(key)) {
......
......@@ -42,12 +42,12 @@
'use strict';
// injected references
var $log, fs;
var $log, $http, $q, fs;
// internal state
var maps = d3.map(),
msgMs = 'MapService.',
bundledUrlPrefix = 'data/map/';
bundledUrlPrefix = '../data/map/';
function getUrl(id) {
if (id[0] === '*') {
......@@ -57,38 +57,61 @@
}
angular.module('onosSvg')
.factory('MapService', ['$log', 'FnService',
.factory('MapService', ['$log', '$http', '$q', 'FnService',
function (_$log_, _fs_) {
function (_$log_, _$http_, _$q_, _fs_) {
$log = _$log_;
$http = _$http_;
$q = _$q_;
fs = _fs_;
function clearCache() {
maps = d3.map();
}
// NOTE: It is expected that mapLayer is a D3 selection of the
// <g> element (a child of zoomLayer) into which the map
// path data will be rendered.
function renderMap(mapLayer) {
// TODO ---
$log.log('Hey, let\'s render the map...');
}
function fetchGeoMap(id) {
if (!fs.isS(id)) {
return null;
}
var url = getUrl(id);
var geomap = maps.get(id);
var promise = maps.get(id);
if (!geomap) {
if (!promise) {
// need to fetch the data and build the object...
geomap = {
var deferred = $q.defer();
promise = deferred.promise;
$http.get(url)
.success(function (data) {
deferred.resolve(data);
})
.error(function (msg, code) {
deferred.reject(msg);
$log.warn(msg, code);
});
promise.meta = {
id: id,
url: getUrl(id),
wasCached: false
url: url,
wasCached: false,
render: renderMap
};
// TODO: use $http service to load map data asynchronously
maps.set(id, geomap);
maps.set(id, promise);
} else {
geomap.wasCached = true;
promise.meta.wasCached = true;
}
return geomap;
return promise;
}
return {
......
......@@ -29,7 +29,7 @@
];
// references to injected services etc.
var $log, ks, zs, gs;
var $log, ks, zs, gs, ms;
// DOM elements
var svg, defs;
......@@ -106,14 +106,15 @@
angular.module('ovTopo', moduleDependencies)
.controller('OvTopoCtrl', [
'$log', 'KeyService', 'ZoomService', 'GlyphService',
'$log', 'KeyService', 'ZoomService', 'GlyphService', 'MapService',
function (_$log_, _ks_, _zs_, _gs_) {
function (_$log_, _ks_, _zs_, _gs_, _ms_) {
var self = this;
$log = _$log_;
ks = _ks_;
zs = _zs_;
gs = _gs_;
ms = _ms_;
// exported state
self.message = 'Topo View Rocks!';
......
......@@ -20,9 +20,7 @@
@author Simon Hunt
*/
describe('factory: fw/svg/map.js', function() {
var $log, fs, ms, d3Elem, geomap;
var urlPrefix = 'data/map/';
var $log, fs, ms, d3Elem, promise;
beforeEach(module('onosUtil', 'onosSvg'));
......@@ -49,51 +47,61 @@ describe('factory: fw/svg/map.js', function() {
});
it('should return null when no parameters given', function () {
geomap = ms.fetchGeoMap();
expect(geomap).toBeNull();
promise = ms.fetchGeoMap();
expect(promise).toBeNull();
});
it('should augment the id of a bundled map', function () {
var id = '*foo';
geomap = ms.fetchGeoMap(id);
expect(geomap).toBeDefined();
expect(geomap.id).toBe(id);
expect(geomap.url).toBe('data/map/foo.json');
promise = ms.fetchGeoMap(id);
expect(promise.meta).toBeDefined();
expect(promise.meta.id).toBe(id);
expect(promise.meta.url).toBe('../data/map/foo.json');
});
it('should treat an external id as the url itself', function () {
var id = 'some/path/to/foo';
geomap = ms.fetchGeoMap(id);
expect(geomap).toBeDefined();
expect(geomap.id).toBe(id);
expect(geomap.url).toBe(id + '.json');
promise = ms.fetchGeoMap(id);
expect(promise.meta).toBeDefined();
expect(promise.meta.id).toBe(id);
expect(promise.meta.url).toBe(id + '.json');
});
it('should cache the returned objects', function () {
var id = 'foo';
geomap = ms.fetchGeoMap(id);
expect(geomap).toBeDefined();
expect(geomap.wasCached).toBeFalsy();
expect(geomap.tagged).toBeUndefined();
promise = ms.fetchGeoMap(id);
expect(promise).toBeDefined();
expect(promise.meta.wasCached).toBeFalsy();
expect(promise.tagged).toBeUndefined();
geomap.tagged = 'I woz here';
promise.tagged = 'I woz here';
geomap = ms.fetchGeoMap(id);
expect(geomap).toBeDefined();
expect(geomap.wasCached).toBeTruthy();
expect(geomap.tagged).toEqual('I woz here');
promise = ms.fetchGeoMap(id);
expect(promise).toBeDefined();
expect(promise.meta.wasCached).toBeTruthy();
expect(promise.tagged).toEqual('I woz here');
});
it('should clear the cache when asked', function () {
var id = 'foo';
geomap = ms.fetchGeoMap(id);
expect(geomap.wasCached).toBeFalsy();
promise = ms.fetchGeoMap(id);
expect(promise.meta.wasCached).toBeFalsy();
geomap = ms.fetchGeoMap(id);
expect(geomap.wasCached).toBeTruthy();
promise = ms.fetchGeoMap(id);
expect(promise.meta.wasCached).toBeTruthy();
ms.clearCache();
geomap = ms.fetchGeoMap(id);
expect(geomap.wasCached).toBeFalsy();
promise = ms.fetchGeoMap(id);
expect(promise.meta.wasCached).toBeFalsy();
});
it('should load USA into cache', function () {
var id = '*continental_us';
promise = ms.fetchGeoMap(id);
expect(promise).toBeDefined();
expect(promise.meta.id).toBe(id);
expect(promise.meta.url).toBe('../data/map/continental_us.json');
// TODO: WIP -- after a pause, the data should be there!!!
});
});
......