1 /** @ignore */
  2 (function(){
  3   ////////////////////////////////////////////////////////////////////////////
  4   //
  5   // Classes
  6   //
  7   ////////////////////////////////////////////////////////////////////////////
  8 
  9   // Class definition borrows heavily from John Resig's blog post at:
 10   // http://ejohn.org/blog/simple-javascript-inheritance/
 11   // This in turn borrows heavily from Dean Edward's Base 2:
 12   // http://code.google.com/p/base2/
 13   // Class definition is secondary to the core traits functionality, which
 14   // is the focus of this project.  Mssr. Resig's class implementation was
 15   // chosen to support traits because it's concise and adds a 'super' reference
 16   // to 'this', which allows trait methods to more effectively preserve the
 17   // "flattening property" as described in the traits research paper.
 18   //
 19   // Just about any JavaScript implementation of pseudo-classical inheritance
 20   // could be plugged in here (YUI's, Tibco GI's, Ext's, etc.) with little
 21   // difficulty.
 22 
 23 
 24   // initializing is a flag used in the constructor to indicate that we want
 25   // to create a dummy instance of a class for the purpose of prototype
 26   // chaining.  We avoid a normal constructor call because executing the full
 27   // constructor may have expensive and undesired side effects.
 28   var initializing = false;
 29 
 30   // fnTest is applied to methods to check if they have references to _super.
 31   // The machinery used to hook up _super is slightly expensive, so we want
 32   // to avoid enabling it when possible.
 33   // Unfortunately, not all JS implementations will return the source code
 34   // of a function when casted to a String, so we do a capability test here.
 35   // JS implementations that can not inspect source code will always set up
 36   // _super in method calls while the better implementations will only set up
 37   // _super if the word _super is found in the source code.  Note that this
 38   // means _super won't be set up properly if you do something silly like
 39   // this["_sup"+"er"]()
 40   var fnTest = /xyz/.test(function(){xyz;}) ?
 41                  /\b_super\b/ :
 42                  { test: function(){return true;} };
 43 
 44 
 45   // Traits may be added to instances via the public instance method 'use'.
 46   // This function accomplishes that functionality (and is aliased to 'use'
 47   // below.
 48   var instanceUse = function(uses) {
 49     // create a new subclass of this object's class with the new trait info
 50     var anonymousSubClass = Class.define({
 51       superclass: this.prototype,
 52       uses: uses
 53     });
 54 
 55     // make the object an instance of the new subclass
 56     this.prototype = anonymousSubClass.prototype;
 57   };
 58 
 59   var klassUse = function(uses, _klass_prototype, _klass_properties) {
 60     _klass_prototype = _klass_prototype || this.prototype;
 61     _klass_properties = _klass_properties || this;
 62 
 63     var trait = Trait.define({
 64       uses: o.uses,
 65       _klass_prototype: _klass_prototype,
 66       _klass_properties: _klass_properties
 67     });
 68 
 69     // Augment the class with the newly created trait
 70     for (var method_name in trait._exports) {
 71       if (!trait._exports.hasOwnProperty(method_name)) continue;
 72 
 73       // Class methods (but not superclass methods) have precedence over
 74       // trait methods, so don't import the method if this class already
 75       // has a method with the same name.
 76       if (_klass_properties.hasOwnProperty(method_name)) {
 77         // If the trait method is being overriden by the class, the
 78         // corresponding class slot must be callable.
 79         if (typeof _klass_properties[method_name] != "function") {
 80           throw new Trait.TraitError(method_name +
 81               " overrides trait method and must be a function.");
 82         }
 83       } else {
 84         prop[method_name] = trait._exports[method_name];
 85       }
 86     }
 87   };
 88 
 89   /**
 90    * Global namespace for class related functions.
 91    * @namespace
 92    * @name Class
 93    */
 94   this.Class = function(){};
 95 
 96   /**
 97    * Define a new class.  In the traits model of object oriented programming
 98    * a class consists of:
 99    * <ul>
100    * <li>a superclass</li>
101    * <li>a set of composed traits</li>
102    * <li>a collection of methods and state variables</li>
103    * </ul>
104    * This structure is directly mirrored in the argument structure of
105    * Class.define.
106    *
107    * <p>
108    * A number of special properties are assigned to the class at definition
109    * time:
110    * </p>
111    * <ul>
112    * <li>A static reference 'superclass' is added which points at the
113    * superclass's constructor function.
114    * </li>
115    * <li>The static 'constructor' reference is pointed at the class itself so
116    * that the 'typeof' and 'instanceof' operators will behave as expected.
117    * </li>
118    * <li>A static and instance method 'does' is added as well.  This method
119    * behaves just like {@link Trait#does} with the notable difference that it
120    * also includes any superclasses's traits in its output.
121    * </li>
122    * <li>Finally, an instance method '_super' is added such that invoking it in
123    * any other instance method will call the first function with the same name
124    * defined in the class's superclass prototype chain.
125    * </li>
126    * </ul>
127    *
128    * <p>
129    * Conflicts among instance properties are resolved in the following order:
130    * class members override trait members and superclass members, and trait
131    * members override superclass members.
132    * </p>
133    *
134    * <p>
135    * The class constructor is specified as a method named init passed into the
136    * o.members argument.
137    * </p>
138    *
139    * @example
140    * var HappyFace = Class.define({
141    *   superclass: Doodle,
142    *   uses: [
143    *     TFace,
144    *     TColoredCircle.aliases({drawColoredCircle: 'draw'})
145    *   ],
146    *   members: {
147    *     // constructor
148    *     init: function(color) {
149    *       this.isDrawn = false;
150    *       if (color)
151    *         this.setColor(color);
152    *     },
153    *     // draw a happy face
154    *     draw: function() {
155    *       // call Doodle's draw method to set up the canvas
156    *       this._super();
157    *       // draw a colored circle
158    *       this.drawColoredCircle();
159    *       // draw the face
160    *       this.drawEyes();
161    *       this.drawMouth():
162    *       // record that the happy face has been drawn
163    *       this.isDrawn = true;
164    *     },
165    *     // color of the happy face (default is yellow)
166    *     color: 'yellow',
167    *     getColor: function() { return this.color },
168    *     setColor: function(color) { this.color = color }
169    *   }
170    * });
171    *
172    * // draw a blue happy face
173    * var hf = new HappyFace('blue');
174    * hf.draw();
175    * log(hf.isDrawn); // => true
176    * log(hf.does(TFace)); // => true
177    * log(HappyFace.does(TColoredCircle)); // => true
178    * log(HappyFace.superclass === Doodle); // => true
179    *
180    * @name Class.define
181    * @static
182    * @function
183    *
184    * @throws {Trait.TraitError} Throws an error if the trait arguments are
185    *    invalid, there is an unresolved conflict, or there is an unfullfilled
186    *    trait requirement.
187    * @return {Function} Constructor for the newly created class.
188    * @param {Object} o The class configuration object.
189    * @param {Function} [o.superclass] Superclass from which this class
190    *    inherits.  Default superclass is the global object Class.
191    * @param {Trait|Trait[]} [o.uses] A list of traits that will be composed
192    *    into this class.  This happens by first constructing a new anonymous
193    *    trait and then adding each of that anonymous trait's exported methods
194    *    into the class prototype.  Trait methods are not copied, however, if
195    *    there is a method defined at the class level with the same name
196    *    (because class level methods override trait level methods).  Unlike
197    *    normal trait definition, all trait requirements must be fullfilled at
198    *    class definition time, either by one of the composed traits, a class
199    *    method, or a superclass method.  See the documentation for o.uses in
200    *    {@link Trait} for full details on how to specify this argument.
201    * @param {Object} [o.members] Public instance members to be copied into this
202    *    class's prototype.
203    */
204   Class.define = function(o) {
205     if (!o.superclass) {
206       o.superclass = Class;
207     }
208 
209     var _super = o.superclass.prototype,
210         prop = o.members || {};
211 
212     // Instantiate a base class (but only create the instance,
213     // don't run the init constructor)
214     initializing = true;
215     var prototype = new o.superclass();
216     initializing = false;
217 
218     // Merge in traits (if any) to list of properties (prop)
219     if (o.uses) {
220       var trait = Trait.define({
221         uses: o.uses,
222         _klass_prototype: prototype,
223         _klass_properties: prop
224       });
225 
226       // Augment the class with the newly created trait
227       for (var method_name in trait._exports) {
228         if (!trait._exports.hasOwnProperty(method_name)) continue;
229 
230         // Class methods (but not superclass methods) have precedence over
231         // trait methods, so don't import the method if this class already
232         // has a method with the same name.
233         if (prop.hasOwnProperty(method_name)) {
234           // If the trait method is being overriden by the class, the
235           // corresponding class slot must be callable.
236           if (typeof prop[method_name] != "function") {
237             throw new Trait.TraitError(method_name +
238                 " overrides trait method and must be a function.");
239           }
240         } else {
241           prop[method_name] = trait._exports[method_name];
242         }
243       }
244     }
245 
246     // Copy the properties over to the new prototype
247     for (var name in prop) {
248       if (!prop.hasOwnProperty(name)) continue;
249 
250       // Check if we're overwriting an existing function. If we are,
251       // create a closure to point this._super to the overriden method
252       // in the superclass only while the execution is running.  We
253       // preserve the original value of _super and restore it so that if
254       // a method x calls another method y this._super will work as
255       // expected in method x after calling y.
256       prototype[name] = typeof prop[name] == "function" &&
257         typeof _super[name] == "function" && fnTest.test(prop[name]) ?
258         (function(name, fn){
259           return function() {
260             var tmp = this._super;
261 
262             // Add a new ._super() method that is the same method
263             // but on the superclass.  Naming it _super because
264             // super (no underscore) is a JS reserved word.
265             this._super = _super[name];
266 
267             // The method only need to be bound temporarily, so we
268             // remove it when we're done executing
269             var ret = fn.apply(this, arguments);
270             this._super = tmp;
271 
272             return ret;
273           };
274         })(name, prop[name]) :
275         prop[name];
276     }
277 
278     // The dummy class constructor
279     var klass = function() {
280       // All construction is actually done in the init method
281       if ( !initializing && this.init ) {
282         this.init.apply(this, arguments);
283       }
284     }
285 
286     // Populate our constructed prototype object
287     klass.prototype = prototype;
288 
289     // Enforce the constructor to be what we expect
290     klass.constructor = klass;
291 
292     // Add a static reference to the superclass
293     klass.superclass = o.superclass;
294 
295     // Alias the does operator from the implict anonymous trait as an
296     // instance and static method of the class.  Return false/empty if
297     // no traits are associated with this class (or any superclass).
298     klass.does = function(trait_ref) {
299       if (!trait) {
300         if (klass.superclass.does)
301           return klass.superclass.does(trait_ref);
302         if (trait_ref)
303           return false;
304         return [];
305       }
306 
307       var used_traits = trait.does(trait_ref);
308       if (klass.superclass.does) {
309         if (trait_ref)
310           return used_traits || klass.superclass.does(trait_ref);
311         // merge inherited traits and those used in this class (note:
312         // concat([]) is an idiom for copying an array).  It would be quicker
313         // to sort these arrays and then merge algorithmically, but JS
314         // doesn't appear to sort references consistently using the
315         // Array.sort method...it sorts by lexicographical order of source
316         // code string in Gecko, which is definitely not what we want...
317         var inherited_traits = klass.superclass.does(trait_ref).concat([]);
318         for (var i = used_traits.length-1; i >= 0; i--) {
319           if (inherited_traits.indexOf(used_traits[i]) === -1)
320             inherited_traits.push(used_traits[i]);
321         }
322         return inherited_traits;
323       }
324 
325       return used_traits;
326     };
327 
328     if (!klass.prototype.hasOwnProperty("does")) {
329       klass.prototype.does = klass.does;
330     }
331 
332     if (!klass.prototype.hasOwnProperty("use")) {
333       klass.prototype.use = instanceUse;
334     }
335 
336     return klass;
337   };
338 
339   ////////////////////////////////////////////////////////////////////////////
340   //
341   // Traits
342   //
343   ////////////////////////////////////////////////////////////////////////////
344 
345   // Some helper functions used by Trait
346 
347   // Is o an array?
348   function isArray(o) {
349     return Object.prototype.toString.apply(o) === '[object Array]';
350   }
351 
352   // Make o an array if it isn't one already
353   function makeArray(o) {
354     if (o)
355       return isArray(o) ? o : [o];
356     return [];
357   }
358 
359   // Convert ['a', 'b'] to { 'a':true, 'b':true }
360   // Also converts 'a' to { 'a':true }
361   function stringArrayToHash(a) {
362     if (!a) return {};
363     var ret = {};
364     if (!isArray(a)) {
365       ret[a] = true;
366       return ret;
367     }
368     for (var i = a.length-1; i >=0; i--)
369       ret[a[i]] = true;
370     return ret;
371   }
372 
373   // Merge sender's properties into receiver
374   function merge(receiver, sender) {
375     for (var i in sender) {
376       if (!sender.hasOwnProperty(i)) continue;
377       receiver[i] = sender[i];
378     }
379     return receiver;
380   }
381 
382   this.Trait = Class.define({
383     members: /** @lends Trait.prototype */ {
384       /**
385        * <p>
386        * A trait is a group of pure methods that serves as a building block for
387        * classes and is a primitive unit of code reuse. In this model, classes
388        * are composed from a set of traits by specifying glue code that
389        * connects the traits together and accesses the necessary state.  If you
390        * are unfamiliar with the general object oriented programming notion of
391        * a trait it would serve you well to check out the
392        * <a href="http://code.google.com/p/jstraits/wiki/TraitSynopsis">synopsis
393        * and examples</a> before reading the rest of this documentation.
394        * </p>
395        *
396        * <p>
397        * The constructor creates a new trait for use in other traits or classes.
398        * The factory method {@link Trait.define} is the preferred way to
399        * instantiate new traits, as opposed to calling 'new Trait(...)'
400        * directly.
401        * </p>
402        *
403        * @example
404        * var TColoredCircle = new Trait({
405        *   uses: [TColor, TCircle.aliases({'drawOutline': 'draw'})],
406        *   requires: 'fillWithColor',
407        *   methods: {
408        *     draw: function() {
409        *       // draw a colored circle
410        *       this.drawOutline();
411        *       this.fillWithColor(this.getColor());
412        *     }
413        *   }
414        * });
415        *
416        * @constructs
417        * @see Trait.define
418        * @throws {Trait.TraitError} Throws an error if the trait definition
419        *    arguments are invalid, the trait definition is inconsistent, or
420        *    there is an unresolved conflict.
421        * @param {Object} o The trait configuration object.
422        * @param {Trait|Trait[]} [o.uses] Other trait(s) that will be composed
423        *    into this new trait.  Note that trait composition is both
424        *    associative and commutative, so if specifying more than one trait
425        *    the order does not matter.  To alias or exclude methods from
426        *    subtraits as they are composed, call {@link Trait#aliases} or
427        *    {@link Trait#excludes}.  Calls to these functions may be chained.
428        *    Passing a trait into o.uses causes the methods from that trait
429        *    (plus any aliases and modulo any excludes) to be added to the new
430        *    trait.  If any of these exported method names conflict with another
431        *    trait specified in o.uses, the conflict must be resolved (unless
432        *    the conflicting method names point to the exact same function).
433        *    Conflicts may be resolved by either 1) overriding the method in
434        *    o.methods 2) overriding the method at the class level (if this
435        *    trait is being defined as part of a class) or 3) excluding all but
436        *    one of the conflicting methods.
437        * @param {String|String[]} [o.requires] A list of method names that must 
438        *    be implemneted before this trait can function properly.  A trait
439        *    may have open requirements, but all its requirements must be
440        *    fulfilled when it is composed into a class.  Requirements can be
441        *    satisfied by other traits or class methods.
442        * @param {Object} [o.methods] A dictionary of methods that this trait
443        *    exports (in addition to those composed in o.uses).  Methods may
444        *    access instance methods, but should not directly access instance
445        *    variables.  References to instance methods that are not deinfed in
446        *    this trait or a composed subtrait should have their method names
447        *    placed in the o.requires parameter.
448        */
449       init: function(o) {
450         // Normalize arguments
451         this._subtraits = makeArray(o.uses);
452         this._requires = stringArrayToHash(o.requires);
453         this._exports = o.methods ? o.methods : {};
454 
455         // The set of exported methods and required methods of a trait must
456         // be disjoint
457         var method_name;
458         for (method_name in this._requires) {
459           if (!this._requires.hasOwnProperty(method_name)) continue;
460           if (this._exports.hasOwnProperty(method_name)) {
461             throw new Trait.TraitError("Trait cannot require and provide " +
462               "the same method " + method_name);
463           }
464         }
465 
466         // Compose subtraits with this trait
467         var subtrait, exports, i, excludes = {};
468         for (i = this._subtraits.length-1; i >= 0; i--) {
469           subtrait = this._subtraits[i];
470 
471           // Merge aliases into list of exports.
472           exports = merge({}, subtrait._exports);
473           if (subtrait._aliases)
474             merge(exports, subtrait._aliases);
475 
476           // Note if any methods were excluded from this subtrait. If they
477           // were a method with the same name will need to be provided in this
478           // trait. We'll check this after composition finishes. Also,
479           // remove method from list of exports.
480           if (subtrait._excludes) {
481             for (method_name in subtrait._excludes) {
482               if (!subtrait._excludes.hasOwnProperty(method_name)) continue;
483               delete exports[method_name];
484               merge(excludes, subtrait._excludes);
485             }
486           }
487 
488           // Compose the subtrait's exported methods into this trait
489           for (method_name in exports) { // each exported method
490             if (!exports.hasOwnProperty(method_name)) continue;
491             // If this method name is overriden at the class level don't
492             // compose it.  Overriding at the class level also resolves any
493             // potential conflicts for this method name, so we don't have to
494             // check for that.  Superclass methods, however, should be
495             // overriden by trait methods, so we won't check the classes
496             // prototype here.
497             if (o._klass_prototype &&
498                 o._klass_properties.hasOwnProperty(method_name) &&
499                 typeof o._klass_properties[method_name] == "function")
500             {
501               // overriding at class level, do nothing
502               continue;
503             }
504 
505             // If we've already exported a method with name method_name and
506             // that exported method is from another subtrait then we have
507             // a TraitConflict.  Otherwise, if the already exported method is
508             // defined in this trait, it overrides methods with the same name
509             // from any subtrait (and hence we don't assign the subtrait's
510             // method here). An error is not thrown if the subtrait's method
511             // is the same as the one that already exists.
512             if (this._exports.hasOwnProperty(method_name)) {
513               if ((!o.methods || !o.methods.hasOwnProperty(method_name)) &&
514                  this._exports[method_name] != exports[method_name])
515               {
516                 throw new Trait.TraitError("Multiple subtraits provide " +
517                    "method " + method_name + " creating a conflict. " +
518                    "Exclude all but one of the methods or override the " +
519                    "method in the trait/class to resolve.");
520               }
521               continue;
522             }
523 
524             // No overrides and no conflicts so merge the subtrait's exported
525             // method into this trait.
526             this._exports[method_name] = exports[method_name];
527           }
528 
529           // Compose the subtrait's required methods into this trait
530           for (method_name in subtrait._requires) {
531             if (!subtrait._requires.hasOwnProperty(method_name)) continue;
532             if (!this._exports.hasOwnProperty(method_name)) {
533               this._requires[method_name] = true;
534             }
535           }
536 
537           // Clear out alias and exclude data (which only makes sense in
538           // the context of a 'use' clause).
539           delete subtrait._aliases
540           delete subtrait._excludes
541         }
542 
543         // Make sure that excluded methods have been overriden either by
544         // another trait or class
545         for (method_name in excludes) {
546           if (!excludes.hasOwnProperty(method_name)) continue;
547           if (!this._exports.hasOwnProperty(method_name) &&
548               (!o._klass_prototype ||
549                (typeof o._klass_prototype[method_name] != "function" &&
550                 typeof o._klass_properties[method_name] != "function"
551                )))
552           {
553             throw new Trait.TraitError("Excluded method " + method_name +
554                 " must be provided by another class or trait.");
555           }
556         }
557 
558         // Prune any requirements that are fullfilled by the composed trait.
559         // If this trait is being defined in a class, make sure that all other
560         // requirements are fullfilled by the class.
561         for (method_name in this._requires) {
562           if (!this._requires.hasOwnProperty(method_name)) continue;
563           if (this._exports.hasOwnProperty(method_name)) {
564             delete this._requires[method_name];
565           } else if (o._klass_prototype &&
566                      (typeof o._klass_prototype[method_name] != "function" &&
567                       typeof o._klass_properties[method_name] != "function"
568                      ))
569 
570           {
571             throw new Trait.TraitError("Trait requirement " + method_name +
572                 " not fullfilled by class.");
573           }
574         }
575       },
576 
577       /**
578        * Alias a method to a different name during trait composition.  Aliases
579        * should only be used in a 'uses' clause inside a class or trait
580        * definition.  It may be chained with {@link Trait#excludes}.  Aliasing
581        * a method causes it to be copied under the new alias name in addition
582        * to the original method name.  Multiple aliases may be made to the
583        * same function.  Aliases are treated exactly like normal method names
584        * during trait composition.
585        * 
586        * @throws {Trait.TraitError} Throws a TraitError if attempting to alias a
587        *     non-existent function, create an alias with the same name as a
588        *     natively exported method, or create an alias with the same name
589        *     as one of the required method names.
590        * @return {Trait} this
591        * @param {Object} o A String to String mapping of alias names to exported
592        *     method names.
593        */
594       aliases: function(o) {
595         this._aliases = this._aliases || {};
596         // Check that alias targets exist, aliases don't override existing
597         // methods, and aliases/requirements are disjoint
598         for (var alias in o) {
599           if (!o.hasOwnProperty(alias)) continue;
600           if (!this._exports.hasOwnProperty(o[alias]))
601             throw new Trait.TraitError("can't alias " + alias
602                 + " to " + o[alias] +
603                 " because trait doesn't have that method");
604           if (this._exports.hasOwnProperty(alias))
605             throw new Trait.TraitError("can't create an alias with name " +
606                 alias + " because trait natively exports that method");
607           if (this._requires.hasOwnProperty(alias))
608             throw new Trait.TraitError("can't create an alias with name " +
609                 alias + " because trait requires method with same name");
610           this._aliases[alias] = this._exports[o[alias]];
611         }
612         return this;
613       },
614 
615       /**
616        * Exclude a method during trait composition.  Excludes should only be
617        * used in a 'uses' clause inside a class or trait definition.  It may be
618        * chained with {@link Trait#aliases}.  Excluding a method causes it to
619        * not be copied into the containing class or trait as it normally would.
620        * If a method is excluded a method with the same name must be provided,
621        * either by another trait or a class method.
622        * 
623        * @throws {Trait.TraitError} Throws a TraitError if attempting to exclude
624        *     a method that is not exported by this trait.
625        * @returns {Trait} this
626        * @param {String|String[]} a Method(s) to exclude during trait
627        *     composition.
628        */
629       excludes: function(a) {
630         this._excludes = this._excludes || {};
631         a = makeArray(a);
632         // Check that excluded methods exist
633         for (var i = a.length-1; i >=0; i--) {
634           if (!this._exports.hasOwnProperty(a[i])) {
635             throw new Trait.TraitError("can't exclude method " + a[i] +
636                 " because no such method exists in trait");
637           }
638           this._excludes[a[i]] = true;
639         }
640         return this;
641       },
642 
643       /**
644        * Inspect all traits used by this trait.  Note that this trait is
645        * included in the list of what this trait 'does'. If no argument is
646        * passed, an array of all traits is returned.  If a trait is passed, a
647        * boolean is returned indicating if the specified trait is one of the
648        * composed traits.  This method differs from {@link Trait#subtraits} in
649        * that subtraits only checks for traits specified in the use clause,
650        * while this method recursively checks to see if any of the subtraits'
651        * subraits match, and so on.
652        *
653        * @return {Trait[]|Boolean} List of all traits composed into this trait
654        *     or a boolean indicating if a particular trait was used.
655        * @param {Trait} [trait_ref] Trait to check for inclusion in the list
656        *     of composed traits.
657        */
658       does: function(trait_ref) {
659         // Computing the list of implemented traits can be a little expensive
660         // so lazily generate it on the first invocation of does
661         if (!this._does) {
662           // This trait does itself, its subtraits, and . . .
663           this._does = [this].concat(this._subtraits);
664           // . . . its subtraits' subtratis, etc..
665           var i, j, subsub;
666           for (i = this._subtraits.length-1; i >= 0; i--) {
667             subsub = this._subtraits[i].does();
668             // Since the same trait can be acquired from multiple sources,
669             // need to check traits for uniqueness before adding to _does.
670             // This would be more efficient with a dictionary but JS objects
671             // don't support pointer/reference keys, and I have a feeling that
672             // a hand rolled dictionary implementation is going to be slooow.
673             for (j = subsub.length-1; j >= 0; j--) {
674               if (this._does.indexOf(subsub[j]) === -1)
675                 this._does.push(subsub[j]);
676             }
677           }
678         }
679 
680         if (trait_ref)
681           return this._does.indexOf(trait_ref) >= 0;
682         return this._does;
683       },
684 
685       /**
686        * Inspect method names required by this trait.  If no arguments are
687        * passed, an object with keys representing all the required methods is 
688        * returned.  If a string argument is given, requires returns a boolean
689        * indicating if this trait requires a method with that name.
690        *
691        * @return {Object|Boolean} Object keyed by required method names or
692        *     boolean indicating if a particular method name is required.
693        * @param {String} method_name Method name to check if in required method
694        *     name list.
695        */
696       requires: function(method_name) {
697         if (method_name)
698           return this._requires.hasOwnProperty(method_name) &&
699             this._requires[method_name];
700         return this._requires;
701       },
702 
703       /**
704        * Inspect subtraits used by this trait. Note that only immediate
705        * subtraits are dealt with here (i.e. those passed in the 'uses'
706        * clause). To recursively check if a trait uses another trait see
707        * {@link Trait#does}.  If no argument is passed, an array of all
708        * subtraits is returned.  If a trait is passed, a boolean is returned
709        * indicating if the specified trait is one of the subtraits.
710        *
711        * @return {Trait[]|Boolean} List of all subtraits or boolean indicating
712        *     if a particular subtrait was used.
713        * @param {Trait} [trait_ref] Trait to check for inclusion in the list
714        *     of subtraits.
715        */
716       subtraits: function(trait_ref) {
717         if (trait_ref)
718           return this._subtraits.indexOf(trait_ref) >= 0;
719         return this._subtraits;
720       },
721 
722       /**
723        * Inspect methods exported by this trait.  If no arguments are passed,
724        * an object mapping each method name exported by this trait to its
725        * associated function is returned.  If a string argument is given,
726        * methods checks if this trait exports a method with that name.  If so
727        * it returns the associated function, otherwise it returns undefined.
728        *
729        * @return {Object|Function} Mapping of method names to functions, a
730        *     specific function, or undefined.
731        * @param {String} [method_name] Name of the method to look up in this
732        *     trait's method export list.
733        */
734       methods: function(method_name) {
735         if (method_name)
736           return this._exports.hasOwnProperty(method_name) &&
737             this._exports[method_name];
738         return this._exports;
739       }
740     }
741   });
742 
743   /**
744    * Factory method to create new traits.  Arguments are the same as those
745    * passed to the {@link Trait} constructor.  This static method is the
746    * preferred way to create new traits.
747    *
748    * @example
749    * var TColoredCircle = Trait.define({
750    *   uses: [TColor, TCircle.aliases({'drawOutline': 'draw'})],
751    *   requires: 'fillWithColor',
752    *   methods: {
753    *     draw: function() {
754    *       // draw a colored circle
755    *       this.drawOutline();
756    *       this.fillWithColor(this.getColor());
757    *     }
758    *   }
759    * });
760    *
761    * @static
762    * @memberOf Trait
763    * @name define
764    * @function
765    * @see Trait
766    * @return {Trait}
767    * @throws {Trait.TraitError}
768    * @param {Object} o
769    * @param {Trait|Trait[]} [o.uses]
770    * @param {String|String[]} [o.requires]
771    * @param {Object} [o.methods]
772    */
773   Trait.define = function(o) {
774     return new Trait(o);
775   };
776 
777   Trait.TraitError = Class.define({
778     superclass: Error,
779     members: /** @lends Trait.TraitError.prototype */ {
780       /**
781        * Generic error thrown for any trait related exceptions.
782        *
783        * @constructs
784        * @augments Error
785        * @param {String} msg The message to show when printing out the string.
786        */                                                     
787       init: function(msg) {
788         this.name = "TraitError";
789         this.message = msg;
790       }
791     }
792   });
793 })();
794