Basic implementation of registers

https://fedorahosted.org/freeipa/ticket/3235
This commit is contained in:
Petr Vobornik 2013-01-14 10:24:02 +01:00
parent a31fe2739c
commit ded1bb3642
6 changed files with 504 additions and 0 deletions

View File

@ -0,0 +1,157 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang',
'./construct'
], function(declare, array, lang, construct) {
var Builder = declare(null, {
/**
* Builds objects based on specication.
*
* @class
* @name Builder
*/
/**
* Construct registry
* @property ./Construct_registry
*/
registry: null,
/**
* Build object based on spec.
*
* @param spec {String|Function|Object} Build spec
*
* String: type name, queries registry
* Function: factory or constructor
* Object: spec object
*
* Build control properies of spec object:
* constructor: Function
* factory: Function
* mixim_spec: Boolean
* type: String
*
* All other properties will be passed to object construction method.
*/
build: function(spec) {
var cs = this._get_construction_spec(spec);
var obj = this._build(cs);
return obj;
},
_get_construction_spec: function(spec) {
var cs = {};
if (typeof spec === 'function') {
// spec constructor or factory
if (construct.is_constructor(spec)) {
cs.constructor = spec;
} else {
cs.factory = spec;
}
} else if (typeof spec === 'string') {
// spec is type name
cs = this._query_registry(spec);
} else if (typeof spec === 'object') {
var c = spec.constructor,
f = spec.factory,
m = spec.mixim_spec,
t = spec.type;
var s = lang.clone(spec);
delete s.constructor;
delete s.factory;
delete s.mixim_spec;
delete s.type;
if (c) {
cs.constructor = c;
cs.spec = s;
}
else if (f) {
cs.factory = f;
cs.spec = s;
}
else if (t) {
cs = this._query_registry(t);
if (cs.spec && m) {
lang.mixin(cs.spec, s);
} else {
cs.spec = s;
}
}
}
return cs;
},
_query_registry: function(type) {
if (this.registry) {
return this.registry.get(type);
} else {
throw {
error: 'Build error: construct registry required',
spec: type
};
}
},
_build: function(construction_spec) {
var cs = construction_spec,
obj = null;
if (cs.factory && typeof cs.factory === 'function') {
obj = cs.factory(cs.spec);
} else if (cs.constructor && typeof cs.constructor === 'function') {
obj = new cs.constructor(cs.spec);
} else {
throw {
error: 'Build error: missing or invalid constructor or factory',
spec: cs
};
}
return obj;
},
/**
* Constructor
*
* set spec.registry to use Construct_registry instance
*/
constructor: function(spec) {
spec = spec || {};
if (spec.registry) this.registry = spec.registry;
}
});
return Builder;
});

View File

@ -0,0 +1,103 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang',
'./construct'
], function(declare, array, lang, construct) {
var Construct_registry = declare(null, {
/**
* Registry for storing construction specification.
* @class
* @name Construct_registry
*/
/**
* Internal map for construction specifications.
* @protected
*/
_map: {},
/**
* Registers construction specification
*
* @param type {String|Object} type or construction spec
* @param func {Function} constructor or factory function
* @param [default_spec] {Object} default spec object for given type
*
* @returns Object
*
* Examples:
*
* May be defined by single construction spec object:
* var construction_spec = {
* type: string,
* factory: function,
* constructor: function,
* spec: object
* };
* register(construction_spec);
*
* or by defining them separately as params:
* register(type, factory|constructor, spec);
*/
register: function(type, func, default_spec) {
var spec, f, c;
if (typeof type === 'object') {
spec = type;
} else {
construct.is_constructor(func) ? c = func : f = func;
spec = {
type: type,
factory: f,
constructor: c,
spec: default_spec
};
}
if (typeof spec.type !== 'string' || spec.type !== '') {
throw 'Argument exception: Invalid type';
}
if (typeof spec.factory !== 'function' &&
typeof spec.constructor !== 'function') {
throw 'Argument exception: No factory or constructor defined';
}
this._map[spec.type] = spec;
return spec;
},
/**
* Gets construction specification for given type.
*
* @param type {String} Type name
* @returns Object|null
*/
get: function(type) {
return this._map[type] || null;
}
});
return Construct_registry;
});

View File

@ -0,0 +1,109 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang',
'./construct',
'./Builder',
'./Construct_registry'
], function(declare, array, lang, construct, Builder, Construct_registry) {
var Singleton_registry = declare(null, {
/**
* Registry for storing singleton instances of various items based
* on their type.
*
* @class
* @name Singleton_registry
*/
/**
* Internal map for instances
* @protected
* @type Object
*/
_map: {},
/**
* Builder used for building new instances. Builder has to have a
* Constructor registry set.
* @type Builder
*/
builder: null,
/**
* Gets an instance of given type. Creates a new one if it doesn't
* exist.
*
* When an object is passed in, the function returns it.
*
* @param type {String|Object} Type's name. Or the the object itself.
* @returns Object|null
*/
get: function(type) {
if (typeof type === 'object') return type;
var obj = this._map[type];
if (!obj) {
if (!this.builder) {
throw {
error: 'Object not initialized: missing builder',
ref: this
};
}
obj = this._map[type] = this.builder.build(type);
}
return obj;
},
/**
* Registers construction specification
*
* @param type {String|Object} type or construction spec
* @param func {Function} constructor or factory function
* @param [default_spec] {Object} default spec object for given type
*
* @returns Object
*/
register: function(type, func, default_spec) {
if (!lang.exists('builder.registry', this)) {
throw {
error: 'Object Initialized Exception: builder not initalized',
context: this
};
}
this.builder.registry.register(type, func, default_spec);
},
constructor: function(spec) {
spec = spec || {};
this.builder = spec.builder || new Builder({
registry: new Construct_registry()
});
}
});
return Singleton_registry;
});

View File

@ -0,0 +1,43 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['dojo/_base/declare',
'dojo/_base/array',
'dojo/_base/lang'
], function(declare, array, lang) {
var construct = {
/**
* Helper modules
*/
/**
* Checks if supplied object is a construtor function.
* It can recognize only classes declared by ''dojo/_base/declare''.
*/
is_constructor: function(obj) {
// TODO: Find better method. Check by extend might not be very
// reliable.
return typeof obj === 'function' && typeof obj.extend === 'function';
}
};
return construct;
});

View File

@ -0,0 +1,44 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['./_base/Singleton_registry'], function(Singleton_registry) {
/**
* entities
* @object
* @singleton
*
* A singleton registry for Entities. Registry calls a builder for building
* an instance if it doesn't have one.
*
* = Usage =
*
* == Registration ==
* Registry entity in application initialization phase using:
* entities.register(name, class, spec);
*
* == Obtaining ==
* Get entity by:
* entities.get('entity_name');
*
*/
var entities = new Singleton_registry();
return entities;
});

View File

@ -0,0 +1,48 @@
/* Authors:
* Petr Vobornik <pvoborni@redhat.com>
*
* Copyright (C) 2012 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define(['./_base/Singleton_registry'], function(Singleton_registry) {
/**
* facets
* @object
* @singleton
*
* A singleton registry for Facets. Registry calls a builder for building
* an instance if it doesn't have one.
*
* All facets are singleton. If one wants to use multiple instances of
* one facet class he must registry the same class under a different name.
* This allows to use different spec object for each instance of a facet.
*
* = Usage =
*
* == Registration ==
* Registry facet in application initialization phase using:
* facets.register(name, class, spec);
*
* == Obtaining ==
* Get facet by:
* facets.get('facet_name');
*
*/
var facets = new Singleton_registry();
return facets;
});