All files / src/ui ve.ui.ModeledFactory.js

86.48% Statements 32/37
75% Branches 12/16
100% Functions 3/3
83.87% Lines 26/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                                    1x       1x                               1x 46x                   48x   48x 1512x 1512x 45x 45x 3x             3x               45x 45x         48x     46x 46x     46x 48x 48x 48x 45x 45x 45x   45x       46x    
/*!
 * VisualEditor UserInterface ModeledFactory class.
 *
 * @copyright See AUTHORS.txt
 */
 
/**
 * Mixin for factories whose items associate with specific models.
 *
 * Classes registered with the factory should have a static method named `isCompatibleWith` that
 * accepts a model and returns a boolean.
 *
 * TODO: Create an abstract mixin that specifies which properties a "model" should have
 *
 * @class
 *
 * @constructor
 */
ve.ui.ModeledFactory = function VeUiModeledFactory() {};
 
/* Inheritance */
 
OO.initClass( ve.ui.ModeledFactory );
 
/* Methods */
 
/**
 * Get a list of symbolic names for classes related to a list of models.
 *
 * The lowest compatible item in each inheritance chain will be used.
 *
 * Additionally if the model has other model names listed in a static.suppresses
 * property, those will be hidden when that model is compatible.
 *
 * @param {Object[]} models Models to find relationships with
 * @return {Object[]} List of objects containing `name` and `model` properties, representing
 *   each compatible class's symbolic name and the model it is compatible with
 */
ve.ui.ModeledFactory.prototype.getRelatedItems = function ( models ) {
	const registry = this.registry;
 
	/**
	 * Collect the most specific compatible classes for a model.
	 *
	 * @private
	 * @param {Object} m Model to find compatibility with
	 * @return {Function[]} List of compatible classes
	 */
	function collect( m ) {
		const candidates = [];
 
		for ( const n in registry ) {
			const candidate = registry[ n ];
			if ( candidate.static.isCompatibleWith( m ) ) {
				let add = true;
				for ( let k = 0, kLen = candidates.length; k < kLen; k++ ) {
					Iif (
						candidate.prototype instanceof candidates[ k ] ||
						( candidate.static.suppresses && candidate.static.suppresses.indexOf( candidates[ k ].static.name ) !== -1 )
					) {
						candidates.splice( k, 1, candidate );
						add = false;
						break;
					} else Iif (
						candidates[ k ].prototype instanceof candidate ||
						( candidates[ k ].static.suppresses && candidates[ k ].static.suppresses.indexOf( candidate.static.name ) !== -1 )
					) {
						add = false;
						break;
					}
				}
				Eif ( add ) {
					candidates.push( candidate );
				}
			}
		}
 
		return candidates;
	}
 
	const names = {};
	const matches = [];
	// Collect compatible classes and the models they are specifically compatible with,
	// discarding class's with duplicate symbolic names
	for ( let i = 0, iLen = models.length; i < iLen; i++ ) {
		const model = models[ i ];
		const classes = collect( model );
		for ( let j = 0, jLen = classes.length; j < jLen; j++ ) {
			const name = classes[ j ].static.name;
			Eif ( !names[ name ] ) {
				matches.push( { name: name, model: model } );
			}
			names[ name ] = true;
		}
	}
 
	return matches;
};