%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /www/varak.net/wiki.varak.net/extensions/VisualEditor/lib/ve/src/dm/
Upload File :
Create Path :
Current File : /www/varak.net/wiki.varak.net/extensions/VisualEditor/lib/ve/src/dm/ve.dm.AnnotationSet.js

/*!
 * VisualEditor DataModel AnnotationSet class.
 *
 * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org
 */

/**
 * Annotation set.
 *
 * @constructor
 * @param {ve.dm.IndexValueStore} store Index-value store
 * @param {number[]} [storeIndexes] Array of store indexes
 */
ve.dm.AnnotationSet = function VeDmAnnotationSet( store, storeIndexes ) {
	// Parent constructor
	this.store = store;
	this.storeIndexes = storeIndexes || [];
};

/* Methods */

/**
 * Get the index-value store.
 *
 * @method
 * @return {ve.dm.IndexValueStore} Index-value store
 */
ve.dm.AnnotationSet.prototype.getStore = function () {
	return this.store;
};

/**
 * Get a clone.
 *
 * @method
 * @return {ve.dm.AnnotationSet} Copy of annotation set
 */
ve.dm.AnnotationSet.prototype.clone = function () {
	return new ve.dm.AnnotationSet( this.getStore(), this.storeIndexes.slice( 0 ) );
};

/**
 * Get an annotation set containing only annotations within the set with a specific name.
 *
 * @method
 * @param {string} name Type name
 * @return {ve.dm.AnnotationSet} Copy of annotation set
 */
ve.dm.AnnotationSet.prototype.getAnnotationsByName = function ( name ) {
	return this.filter( function ( annotation ) { return annotation.name === name; } );
};

/**
 * Get an annotation set containing only annotations within the set which are comparable
 * to a specific annotation.
 *
 * @method
 * @param {ve.dm.Annotation} annotation Annotation to compare to
 * @return {ve.dm.AnnotationSet} Copy of annotation set
 */
ve.dm.AnnotationSet.prototype.getComparableAnnotations = function ( annotation ) {
	return this.filter( function ( a ) {
		return ve.compare(
			annotation.getComparableObject(),
			a.getComparableObject()
		);
	} );
};

/**
 * Get an annotation set containing only annotations within the set which are comparable
 * to an annotation from another set.
 *
 * @method
 * @param {ve.dm.AnnotationSet} annotations Annotation set to compare to
 * @return {ve.dm.AnnotationSet} Copy of annotation set
 */
ve.dm.AnnotationSet.prototype.getComparableAnnotationsFromSet = function ( annotations ) {
	return this.filter( function ( a ) {
		return annotations.containsComparable( a );
	} );
};

/**
 * Check if any annotations in the set have a specific name.
 *
 * @method
 * @param {string} name Type name
 * @return {boolean} Annotation of given type exists in the set
 */
ve.dm.AnnotationSet.prototype.hasAnnotationWithName = function ( name ) {
	return this.containsMatching( function ( annotation ) { return annotation.name === name; } );
};

/**
 * Get an annotation or all annotations from the set.
 *
 * set.get( 5 ) returns the annotation at offset 5, set.get() returns an array with all annotations
 * in the entire set.
 *
 * @method
 * @param {number} [offset] If set, only get the annotation at the offset
 * @return {ve.dm.Annotation[]|ve.dm.Annotation|undefined} The annotation at offset, or an array of all
 *  annotations in the set
 */
ve.dm.AnnotationSet.prototype.get = function ( offset ) {
	if ( offset !== undefined ) {
		return this.getStore().value( this.getIndex( offset ) );
	} else {
		return this.getStore().values( this.getIndexes() );
	}
};

/**
 * Get store index from offset within annotation set.
 *
 * @param {number} offset Offset within annotation set
 * @return {number} Store index at specified offset
 */
ve.dm.AnnotationSet.prototype.getIndex = function ( offset ) {
	return this.storeIndexes[ offset ];
};

/**
 * Get all store indexes.
 *
 * @return {Array} Store indexes
 */
ve.dm.AnnotationSet.prototype.getIndexes = function () {
	return this.storeIndexes;
};

/**
 * Get the length of the set.
 *
 * @method
 * @return {number} The number of annotations in the set
 */
ve.dm.AnnotationSet.prototype.getLength = function () {
	return this.storeIndexes.length;
};

/**
 * Check if the set is empty.
 *
 * @method
 * @return {boolean} The set is empty
 */
ve.dm.AnnotationSet.prototype.isEmpty = function () {
	return this.getLength() === 0;
};

/**
 * Check whether a given annotation occurs in the set.
 *
 * Annotations are compared by store index.
 *
 * @method
 * @param {ve.dm.Annotation} annotation Annotation
 * @return {boolean} There is an annotation in the set with the same hash as annotation
 */
ve.dm.AnnotationSet.prototype.contains = function ( annotation ) {
	return this.offsetOf( annotation ) !== -1;
};

/**
 * Check whether a given store index occurs in the set.
 *
 * @method
 * @param {number} storeIndex Store index of annotation
 * @return {boolean} There is an annotation in the set with this store index
 */
ve.dm.AnnotationSet.prototype.containsIndex = function ( storeIndex ) {
	return this.getIndexes().indexOf( storeIndex ) !== -1;
};

/**
 * Check whether the set contains any of the annotations in another set.
 *
 * @method
 * @param {ve.dm.AnnotationSet} set Set to compare the set with
 * @return {boolean} There is at least one annotation in set that is also in the set
 */
ve.dm.AnnotationSet.prototype.containsAnyOf = function ( set ) {
	var i, length,
		setIndexes = set.getIndexes(),
		thisIndexes = this.getIndexes();
	for ( i = 0, length = setIndexes.length; i < length; i++ ) {
		if ( thisIndexes.indexOf( setIndexes[ i ] ) !== -1 ) {
			return true;
		}
	}
	return false;
};

/**
 * Check whether the set contains all of the annotations in another set.
 *
 * @method
 * @param {ve.dm.AnnotationSet} set Set to compare the set with
 * @return {boolean} All annotations in set are also in the set
 */
ve.dm.AnnotationSet.prototype.containsAllOf = function ( set ) {
	var i, length,
		setIndexes = set.getIndexes(),
		thisIndexes = this.getIndexes();
	for ( i = 0, length = setIndexes.length; i < length; i++ ) {
		if ( thisIndexes.indexOf( setIndexes[ i ] ) === -1 ) {
			return false;
		}
	}
	return true;
};

/**
 * Get the offset of a given annotation in the set.
 *
 * @method
 * @param {ve.dm.Annotation} annotation Annotation to search for
 * @return {number} Offset of annotation in the set, or -1 if annotation is not in the set.
 */
ve.dm.AnnotationSet.prototype.offsetOf = function ( annotation ) {
	return this.offsetOfIndex( this.getStore().indexOfValue( annotation ) );
};

/**
 * Get the offset of a given annotation in the set by store index.
 *
 * @method
 * @param {number} storeIndex Store index of annotation to search for
 * @return {number} Offset of annotation in the set, or -1 if annotation is not in the set.
 */
ve.dm.AnnotationSet.prototype.offsetOfIndex = function ( storeIndex ) {
	return this.getIndexes().indexOf( storeIndex );
};

/**
 * Filter the set by an item property.
 *
 * This returns a new set with all annotations in the set for which the callback returned true for.
 *
 * @method
 * @param {Function} callback Function that takes an annotation and returns boolean true to include
 * @param {boolean} [returnBool] For internal use only
 * @return {ve.dm.AnnotationSet|boolean} New set containing only the matching annotations
 */
ve.dm.AnnotationSet.prototype.filter = function ( callback, returnBool ) {
	var i, length, result, storeIndex, annotation;

	if ( !returnBool ) {
		result = this.clone();
		// TODO: Should we be returning this on all methods that modify the original? Might help
		// with chainability, but perhaps it's also confusing because most chainable methods return
		// a new hash set.
		result.removeAll();
	}
	for ( i = 0, length = this.getLength(); i < length; i++ ) {
		storeIndex = this.getIndex( i );
		annotation = this.getStore().value( storeIndex );
		if ( callback( annotation ) ) {
			if ( returnBool ) {
				return true;
			} else {
				result.storeIndexes.push( storeIndex );
			}
		}
	}
	return returnBool ? false : result;
};

/**
 * Check if the set contains an annotation comparable to the specified one.
 *
 * getComparableObject is used to compare the annotations, and should return
 * true if an annotation is found which is mergeable with the specified one.
 *
 * @param {ve.dm.Annotation} annotation Annotation to compare to
 * @return {boolean} At least one comparable annotation found
 */
ve.dm.AnnotationSet.prototype.containsComparable = function ( annotation ) {
	return this.filter( function ( a ) {
		return annotation.compareTo( a );
	}, true );
};

/**
 * Get the first annotation mergeable with the specified one
 *
 * @param {ve.dm.Annotation} annotation Annotation to compare to
 * @return {ve.dm.Annotation|null} First matching annotation
 */
ve.dm.AnnotationSet.prototype.getComparable = function ( annotation ) {
	var i, len, ann;
	for ( i = 0, len = this.getLength(); i < len; i++ ) {
		ann = this.getStore().value( this.getIndex( i ) );
		if ( ann.compareTo( annotation ) ) {
			return ann;
		}
	}
	return null;
};

/**
 * FIXME T126031: Check if the set contains an annotation comparable to the
 * specified one for the purposes of serialization.
 *
 * This method uses getComparableObjectForSerialization which also includes
 * HTML attributes.
 *
 * @param {ve.dm.Annotation} annotation Annotation to compare to
 * @return {boolean} At least one comparable annotation found
 */
ve.dm.AnnotationSet.prototype.containsComparableForSerialization = function ( annotation ) {
	return this.filter( function ( a ) {
		return annotation.compareToForSerialization( a );
	}, true );
};

/**
 * Check if the set contains at least one annotation where a given property matches a given filter.
 *
 * This is equivalent to (but more efficient than) `!this.filter( .. ).isEmpty()`.
 *
 * @see ve.dm.AnnotationSet#filter
 *
 * @method
 * @param {Function} callback Function that takes an annotation and returns boolean true to include
 * @return {boolean} At least one matching annotation found
 */
ve.dm.AnnotationSet.prototype.containsMatching = function ( callback ) {
	return this.filter( callback, true );
};

/**
 * Check if the set contains the same annotations as another set.
 *
 * Compares annotations by their comparable object value.
 *
 * @method
 * @param {ve.dm.AnnotationSet} annotationSet The annotationSet to compare this one to
 * @return {boolean} The annotations are the same
 */
ve.dm.AnnotationSet.prototype.compareTo = function ( annotationSet ) {
	var i, length = this.getIndexes().length;

	if ( length === annotationSet.getLength() ) {
		for ( i = 0; i < length; i++ ) {
			if ( !annotationSet.containsComparable( this.get( i ) ) ) {
				return false;
			}
		}
	} else {
		return false;
	}
	return true;
};

/**
 * Strictly compare two annotation sets for equality.
 *
 * This method only considers two annotation sets to be equal if they contain exactly the same
 * annotations (not just comparable, but with the same index in the IndexValueStore)
 * in exactly the same order.
 *
 * @param {ve.dm.AnnotationSet} set The annotation set to compare this one to
 * @return {boolean} The annotation sets are equal
 */
ve.dm.AnnotationSet.prototype.equalsInOrder = function ( set ) {
	var i, len,
		ourIndexes = this.getIndexes(),
		theirIndexes = set.getIndexes();
	if ( ourIndexes.length !== theirIndexes.length ) {
		return false;
	}
	for ( i = 0, len = ourIndexes.length; i < len; i++ ) {
		if ( ourIndexes[ i ] !== theirIndexes[ i ] ) {
			return false;
		}
	}
	return true;
};

/**
 * Add an annotation to the set.
 *
 * If the annotation is already present in the set, nothing happens.
 *
 * The annotation will be inserted before the annotation that is currently at the given offset. If offset is
 * negative, it will be counted from the end (i.e. offset -1 is the last item, -2 the second-to-last,
 * etc.). If offset is out of bounds, the annotation will be added to the end of the set.
 *
 * @method
 * @param {ve.dm.Annotation} annotation Annotation to add
 * @param {number} offset Offset to add the annotation at
 */
ve.dm.AnnotationSet.prototype.add = function ( annotation, offset ) {
	var storeIndex = this.getStore().index( annotation );
	// negative offset
	if ( offset < 0 ) {
		offset = this.getLength() + offset;
	}
	// greater than length, add to end
	if ( offset >= this.getLength() ) {
		this.push( annotation );
		return;
	}
	// if not in set already, splice in place
	if ( !this.containsIndex( storeIndex ) ) {
		this.storeIndexes.splice( offset, 0, storeIndex );
	}
};

/**
 * Add all annotations in the given set, removing any duplicates (including existing ones).
 *
 * The offset calculation happens before duplicates are removed.
 *
 * @method
 * @param {ve.dm.AnnotationSet} set Set to add to the set
 * @param {number} [offset] Offset at which to insert; defaults to the end of the set

 */
ve.dm.AnnotationSet.prototype.addSet = function ( set, offset ) {
	var indexes = this.getIndexes();
	if ( offset === undefined ) {
		offset = indexes.length;
	}
	this.storeIndexes = OO.simpleArrayUnion(
		indexes.slice( 0, offset ),
		set.getIndexes(),
		indexes.slice( offset )
	);
};

/**
 * Add an annotation at the end of the set.
 *
 * @method
 * @param {ve.dm.Annotation} annotation Annotation to add
 */
ve.dm.AnnotationSet.prototype.push = function ( annotation ) {
	this.pushIndex( this.getStore().index( annotation ) );
};

/**
 * Add an annotation at the end of the set by store index.
 *
 * @method
 * @param {number} storeIndex Store index of annotation to add
 */
ve.dm.AnnotationSet.prototype.pushIndex = function ( storeIndex ) {
	this.storeIndexes.push( storeIndex );
};

/**
 * Remove the annotation at a given offset.
 *
 * @method
 * @param {number} offset Offset to remove item at. If negative, the counts from the end, see add()
 * @throws {Error} Offset out of bounds.
 */
ve.dm.AnnotationSet.prototype.removeAt = function ( offset ) {
	if ( offset < 0 ) {
		offset = this.getLength() + offset;
	}
	if ( offset >= this.getLength() ) {
		throw new Error( 'Offset out of bounds' );
	}
	this.storeIndexes.splice( offset, 1 );
};

/**
 * Remove a given annotation from the set by store index.
 *
 * If the annotation isn't in the set, nothing happens.
 *
 * @method
 * @param {number} storeIndex Store index of annotation to remove
 */
ve.dm.AnnotationSet.prototype.removeIndex = function ( storeIndex ) {
	var offset = this.offsetOfIndex( storeIndex );
	if ( offset !== -1 ) {
		this.storeIndexes.splice( offset, 1 );
	}
};

/**
 * Remove a given annotation from the set.
 *
 * If the annotation isn't in the set, nothing happens.
 *
 * @method
 * @param {ve.dm.Annotation} annotation Annotation to remove
 */
ve.dm.AnnotationSet.prototype.remove = function ( annotation ) {
	var offset = this.offsetOf( annotation );
	if ( offset !== -1 ) {
		this.storeIndexes.splice( offset, 1 );
	}
};

/**
 * Remove all annotations.
 *
 * @method
 */
ve.dm.AnnotationSet.prototype.removeAll = function () {
	this.storeIndexes = [];
};

/**
 * Remove all annotations in a given set from the set.
 *
 * Annotations that aren't in the set are ignored.
 *
 * @method
 * @param {ve.dm.AnnotationSet} set Set to remove from the set
 */
ve.dm.AnnotationSet.prototype.removeSet = function ( set ) {
	this.storeIndexes = OO.simpleArrayDifference( this.getIndexes(), set.getIndexes() );
};

/**
 * Remove all annotations that are not also in a given other set from the set.
 *
 * @method
 * @param {ve.dm.AnnotationSet} set Set to intersect with the set
 */
ve.dm.AnnotationSet.prototype.removeNotInSet = function ( set ) {
	this.storeIndexes = OO.simpleArrayIntersection( this.getIndexes(), set.getIndexes() );
};

/**
 * Reverse the set.
 *
 * This returns a copy, the original set is not modified.
 *
 * @method
 * @return {ve.dm.AnnotationSet} Copy of the set with the order reversed.
 */
ve.dm.AnnotationSet.prototype.reversed = function () {
	var newSet = this.clone();
	newSet.storeIndexes.reverse();
	return newSet;
};

/**
 * Merge another set into the set.
 *
 * This returns a copy, the original set is not modified.
 *
 * @method
 * @param {ve.dm.AnnotationSet} set Other set
 * @return {ve.dm.AnnotationSet} Set containing all annotations in the set as well as all annotations in set
 */
ve.dm.AnnotationSet.prototype.mergeWith = function ( set ) {
	var newSet = this.clone();
	newSet.addSet( set );
	return newSet;
};

/**
 * Get the difference between the set and another set.
 *
 * @method
 * @param {ve.dm.AnnotationSet} set Other set
 * @return {ve.dm.AnnotationSet} New set containing all annotations that are in the set but not in set
 */
ve.dm.AnnotationSet.prototype.diffWith = function ( set ) {
	var newSet = this.clone();
	newSet.removeSet( set );
	return newSet;
};

/**
 * Get the intersection of the set with another set.
 *
 * This requires annotations to be strictly equal. To find annotations which are comparable
 * use the slower #getComparableAnnotationsFromSet with #addSet.
 *
 * @method
 * @param {ve.dm.AnnotationSet} set Other set
 * @return {ve.dm.AnnotationSet} New set containing all annotations that are both in the set and in set
 */
ve.dm.AnnotationSet.prototype.intersectWith = function ( set ) {
	var newSet = this.clone();
	newSet.removeNotInSet( set );
	return newSet;
};

Zerion Mini Shell 1.0