mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add pre and post build operations
https://fedorahosted.org/freeipa/ticket/3235
This commit is contained in:
parent
03d3742376
commit
abdb5455d1
@ -41,17 +41,19 @@ define(['dojo/_base/declare',
|
||||
/**
|
||||
* Build object based on spec.
|
||||
*
|
||||
* @param spec {String|Function|Object} Build spec
|
||||
* @param {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
|
||||
* $constructor: Function
|
||||
* $factory: Function
|
||||
* $mixim_spec: Boolean
|
||||
* $type: String
|
||||
* $pre_ops: []
|
||||
* $post_ops: []
|
||||
*
|
||||
* All other properties will be passed to object construction method.
|
||||
*/
|
||||
@ -78,16 +80,20 @@ define(['dojo/_base/declare',
|
||||
// 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 c = spec.$constructor,
|
||||
f = spec.$factory,
|
||||
m = spec.$mixim_spec,
|
||||
t = spec.$type,
|
||||
pre = spec.$pre_ops,
|
||||
post = spec.$post_ops;
|
||||
|
||||
var s = lang.clone(spec);
|
||||
delete s.constructor;
|
||||
delete s.factory;
|
||||
delete s.mixim_spec;
|
||||
delete s.type;
|
||||
delete s.$constructor;
|
||||
delete s.$factory;
|
||||
delete s.$mixim_spec;
|
||||
delete s.$type;
|
||||
delete s.$pre_ops;
|
||||
delete s.$post_ops;
|
||||
|
||||
if (c) {
|
||||
cs.constructor = c;
|
||||
@ -105,19 +111,30 @@ define(['dojo/_base/declare',
|
||||
cs.spec = s;
|
||||
}
|
||||
}
|
||||
|
||||
cs.pre_ops = cs.pre_ops || [];
|
||||
cs.post_ops = cs.post_ops || [];
|
||||
if (pre) cs.pre_ops.push.call(cs.pre_ops, pre);
|
||||
if (pre) cs.post_ops.push.call(cs.post_ops, post);
|
||||
}
|
||||
|
||||
return cs;
|
||||
},
|
||||
|
||||
/**
|
||||
* Queries registry and returns copy of construction specification
|
||||
*/
|
||||
_query_registry: function(type) {
|
||||
|
||||
if (this.registry) {
|
||||
return this.registry.get(type);
|
||||
var cs = this.registry.get(type);
|
||||
if (!cs) throw construct.no_cs_for_type_error(type);
|
||||
cs = construct.copy_cs(cs);
|
||||
return cs;
|
||||
} else {
|
||||
throw {
|
||||
error: 'Build error: construct registry required',
|
||||
spec: type
|
||||
builder: this
|
||||
};
|
||||
}
|
||||
},
|
||||
@ -125,7 +142,22 @@ define(['dojo/_base/declare',
|
||||
_build: function(construction_spec) {
|
||||
|
||||
var cs = construction_spec,
|
||||
obj = null;
|
||||
obj = null,
|
||||
i;
|
||||
|
||||
if (cs.pre_ops) {
|
||||
for (i=0; i<cs.pre_ops.length; i++) {
|
||||
var preop = cs.pre_ops[i];
|
||||
var preop_t = typeof preop;
|
||||
if (preop_t === 'function') {
|
||||
cs.spec = preop(cs.spec || {});
|
||||
} else if (preop_t === 'object') {
|
||||
lang.mixin(cs.spec, preop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cs.spec = cs.spec || {};
|
||||
|
||||
if (cs.factory && typeof cs.factory === 'function') {
|
||||
obj = cs.factory(cs.spec);
|
||||
@ -138,6 +170,18 @@ define(['dojo/_base/declare',
|
||||
};
|
||||
}
|
||||
|
||||
if (cs.post_ops && obj) {
|
||||
for (i=0; i<cs.post_ops.length; i++) {
|
||||
var postop = cs.post_ops[i];
|
||||
var postop_t = typeof postop;
|
||||
if (postop_t === 'function') {
|
||||
obj = postop(obj);
|
||||
} else if (postop_t === 'object') {
|
||||
lang.mixin(obj, postop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
|
@ -50,10 +50,12 @@ define(['dojo/_base/declare',
|
||||
*
|
||||
* May be defined by single construction spec object:
|
||||
* var construction_spec = {
|
||||
* type: string,
|
||||
* factory: function,
|
||||
* constructor: function,
|
||||
* spec: object
|
||||
* type: String,
|
||||
* factory: Function,
|
||||
* constructor: Function,
|
||||
* spec: Object,
|
||||
* pre_ops: [],
|
||||
* post_ops: []
|
||||
* };
|
||||
* register(construction_spec);
|
||||
*
|
||||
@ -62,13 +64,13 @@ define(['dojo/_base/declare',
|
||||
*/
|
||||
register: function(type, func, default_spec) {
|
||||
|
||||
var spec, f, c;
|
||||
var cs, f, c;
|
||||
|
||||
if (typeof type === 'object') {
|
||||
spec = type;
|
||||
cs = type;
|
||||
} else {
|
||||
construct.is_constructor(func) ? c = func : f = func;
|
||||
spec = {
|
||||
cs = {
|
||||
type: type,
|
||||
factory: f,
|
||||
constructor: c,
|
||||
@ -76,16 +78,87 @@ define(['dojo/_base/declare',
|
||||
};
|
||||
}
|
||||
|
||||
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';
|
||||
if (!cs.pre_ops) cs.pre_ops = [];
|
||||
if (!cs.post_ops) cs.post_ops = [];
|
||||
|
||||
this._check_spec(cs);
|
||||
|
||||
this._map[cs.type] = cs;
|
||||
return cs;
|
||||
},
|
||||
|
||||
/**
|
||||
* Makes a copy of construct specification of original type. Extends
|
||||
* it with values in supplied construct specification.
|
||||
*
|
||||
* @param {String} Original type
|
||||
* @param {String} New type
|
||||
* @param {Object} Construction specification
|
||||
*/
|
||||
copy: function(org_type, new_type, construct_spec) {
|
||||
|
||||
var def_cs = construct_spec;
|
||||
var old_cs = this._check_get(org_type);
|
||||
var cs = construct.copy_cs(old_cs);
|
||||
|
||||
cs.type = new_type;
|
||||
if (def_cs.pre_ops) cs.pre_ops.push.call(cs.pre_ops, def_cs.pre_ops);
|
||||
if (def_cs.post_ops) cs.post_ops.push.call(cs.post_ops, def_cs.post_ops);
|
||||
if (def_cs.factory) cs.factory = def_cs.factory;
|
||||
if (def_cs.constructor) cs.constructor = def_cs.constructor;
|
||||
if (def_cs.spec) {
|
||||
cs.spec = cs.spec || {};
|
||||
lang.mixin(cs.spec, def_cs.spec);
|
||||
}
|
||||
|
||||
this._map[spec.type] = spec;
|
||||
return spec;
|
||||
this._check_spec(cs);
|
||||
|
||||
this._map[cs.type] = cs;
|
||||
return cs;
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers pre operation.
|
||||
*
|
||||
* Purpose of pre operation is to modify spec object before build
|
||||
* operation.
|
||||
*
|
||||
* When op is Function it gets called with spec as a param and should
|
||||
* return modified spec.
|
||||
*
|
||||
* When op is Object, the object gets mixed in into spec.
|
||||
*
|
||||
* @param {type} type
|
||||
* @param {Function|Object} op
|
||||
* @param {Boolean} move op to first position
|
||||
*/
|
||||
register_pre_op: function(type, op, first) {
|
||||
|
||||
var cs = this._check_get(type);
|
||||
if (first) cs.pre_ops.unshift(op);
|
||||
else cs.pre_ops.push(op);
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers post operation.
|
||||
*
|
||||
* Purpose of post operation is to modify built object.
|
||||
*
|
||||
* When op is Function it gets called with built object as a param
|
||||
* and should return modified obj.
|
||||
*
|
||||
* When op is Object, the object gets mixed in into built object. Use
|
||||
* with caution.
|
||||
*
|
||||
* @param {type} type
|
||||
* @param {Function|Object} op
|
||||
* @param {Boolean} move op to first position
|
||||
*/
|
||||
register_post_op: function(type, op, first) {
|
||||
|
||||
var cs = this._check_get(type);
|
||||
if (first) cs.post_ops.unshift(op);
|
||||
else cs.post_ops.push(op);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -96,6 +169,28 @@ define(['dojo/_base/declare',
|
||||
*/
|
||||
get: function(type) {
|
||||
return this._map[type] || null;
|
||||
},
|
||||
|
||||
_check_get: function(type) {
|
||||
var cs = this.get(type);
|
||||
if (!cs) throw construct.no_cs_for_type_error(type);
|
||||
return cs;
|
||||
},
|
||||
|
||||
_check_spec: function(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';
|
||||
}
|
||||
if (!lang.isArrayLike(spec.pre_ops)) {
|
||||
throw 'Argument exception: Invalid pre_ops type.';
|
||||
}
|
||||
if (!lang.isArrayLike(spec.post_ops)) {
|
||||
throw 'Argument exception: Invalid post_ops type.';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -37,6 +37,26 @@ define(['dojo/_base/declare',
|
||||
// TODO: Find better method. Check by extend might not be very
|
||||
// reliable.
|
||||
return typeof obj === 'function' && typeof obj.extend === 'function';
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates copy of construction specification
|
||||
*
|
||||
* It makes sure that pre_ops, post_ops and spec are new Arrays/Object
|
||||
*/
|
||||
copy_cs: function(org_cs) {
|
||||
var cs = lang.clone(org_cs);
|
||||
if (cs.spec) cs.spec = lang.clone(cs.spec);
|
||||
cs.pre_ops = cs.pre_ops.slice(0);
|
||||
cs.post_ops = cs.pre_ops.slice(0);
|
||||
return cs;
|
||||
},
|
||||
|
||||
no_cs_for_type_error: function(type) {
|
||||
return {
|
||||
error: 'No construction specification for given type',
|
||||
type: type
|
||||
};
|
||||
}
|
||||
};
|
||||
return construct;
|
||||
|
Loading…
Reference in New Issue
Block a user