2 Copyright (c) 2012, Yahoo! Inc. All rights reserved.
3 Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
6 var util = require('util'),
7 path = require('path'),
9 abbrev = require('abbrev');
11 function Factory(kind, dir, allowAbbreviations) {
14 this.allowAbbreviations = allowAbbreviations;
16 this.abbreviations = null;
21 knownTypes: function () {
22 var keys = Object.keys(this.classMap);
27 resolve: function (abbreviatedType) {
28 if (!this.abbreviations) {
29 this.abbreviations = abbrev(this.knownTypes());
31 return this.abbreviations[abbreviatedType];
34 register: function (constructor) {
35 var type = constructor.TYPE;
36 if (!type) { throw new Error('Could not register ' + this.kind + ' constructor [no TYPE property]: ' + util.inspect(constructor)); }
37 this.classMap[type] = constructor;
38 this.abbreviations = null;
41 create: function (type, opts) {
42 var allowAbbrev = this.allowAbbreviations,
43 realType = allowAbbrev ? this.resolve(type) : type,
46 Cons = realType ? this.classMap[realType] : null;
47 if (!Cons) { throw new Error('Invalid ' + this.kind + ' [' + type + '], allowed values are ' + this.knownTypes().join(', ')); }
48 return new Cons(opts);
51 loadStandard: function (dir) {
53 fs.readdirSync(dir).forEach(function (file) {
54 if (file !== 'index.js' && file.indexOf('.js') === file.length - 3) {
56 that.register(require(path.resolve(dir, file)));
58 console.error(ex.message);
59 console.error(ex.stack);
60 throw new Error('Could not register ' + that.kind + ' from file ' + file);
66 bindClassMethods: function (Cons) {
67 var tmpKind = this.kind.charAt(0).toUpperCase() + this.kind.substring(1), //ucfirst
68 allowAbbrev = this.allowAbbreviations;
70 Cons.mix = Factory.mix;
71 Cons.register = this.register.bind(this);
72 Cons.create = this.create.bind(this);
73 Cons.loadAll = this.loadStandard.bind(this, this.dir);
74 Cons['get' + tmpKind + 'List'] = this.knownTypes.bind(this);
76 Cons['resolve' + tmpKind + 'Name'] = this.resolve.bind(this);
81 Factory.mix = function (cons, proto) {
82 Object.keys(proto).forEach(function (key) {
83 cons.prototype[key] = proto[key];
87 module.exports = Factory;