/**
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.waveprotocol.wave.model.document;
import org.waveprotocol.wave.model.util.ReadableStringMap;
import org.waveprotocol.wave.model.util.ReadableStringSet;
/**
* An annotation set which supports querying only.
*
* An annotation set is conceptually a map of key-value pairs for every item in
* an XML document. An "item" is a start tag, end tag, or text character. All
* keys have a default value of null in every position.
*
* The set of items referred to by a range is the set of items with location
* greater than or equal to start, and strictly less than end. Start must be
* greater than or equal to zero, end must be greater than or equal to start,
* and end must be less than or equal to {@code size()}. Implementations are
* not required to detect violations of these conditions, but if they do, they
* should throw an IndexOutOfBoundsException.
*
* TODO(danilatos): More detailed / link to some design doc or similar?
*
* @param <V> base type of values that may be placed in this set. These values
* must have immutable semantics - the annotation set implementation must
* be free to reuse a given value in multiple places, and the values must
* implement {@code equals()} and {@code hashCode()} correctly.
*
* @author ohler@google.com (Christian Ohler)
* @author danilatos@google.com (Daniel Danilatos)
*/
public interface ReadableAnnotationSet<V> {
/**
* @return the size of the document
*/
int size();
/**
* Finds the first item within a range with the specified key having a value
* other than fromValue.
*
* @param start start of the range to search
* @param end end of the range to search
* @param key key to search for
* @param fromValue value to check for change from
* @return the location of the first change, or -1 if there is no change
*/
int firstAnnotationChange(int start, int end, String key, V fromValue);
/**
* Finds the last item within a range with the specified key having a value
* other than fromValue, and returns the position to the right of it
* (its index plus one).
*
* If all items in the given range have the value fromValue, returns -1.
*
* @param start start of the range to search
* @param end end of the range to search
* @param key key to search for
* @param fromValue value to check for change from
* @return the position to the right of the last change, or -1 if there is
* no change
*/
int lastAnnotationChange(int start, int end, String key, V fromValue);
/**
* Gets the value of an annotation for a key on the item at the given
* location.
*
* @param location a document location
* @param key key to read
* @return annotation value
*/
V getAnnotation(int location, String key);
/**
* Call the callback for all annotations at the specified location, in
* undefined order.
*/
void forEachAnnotationAt(int location, ReadableStringMap.ProcV<V> callback);
/**
* Creates an AnnotationCursor over the specified range and key set.
*
* NOTE(ohler): We should deprecate/remove this. Use annotationIntervals()
* or rangedAnnotations() instead.
*
* @param start start of the range
* @param end end of the range
* @param keys key set for which to search for changes
* @return the new annotation cursor
*/
AnnotationCursor annotationCursor(int start, int end, ReadableStringSet keys);
/**
* Permits iteration over the annotation intervals that overlap a given range
* for a given key set.
*
* The annotation intervals returned may extend beyond the boundaries
* specified by start and end.
*
* NOTE: The iterator retains ownership of the AnnotationInterval objects
* that it returns and may modify them destructively to reuse them.
*
* @param start start of the range
* @param end end of the range
* @param keys key set to which to project the annotation set; null means all
* keys
*/
Iterable<AnnotationInterval<V>> annotationIntervals(int start, int end, ReadableStringSet keys);
/**
* Permits iteration over the ranged annotations that overlap a given range
* for a given key set.
*
* The ranged annotations returned may extend beyond the boundaries specified
* by start and end.
*
* The ranged annotations returned provide a complete coverage of the given
* range, including null values. It is easier to skip null values when they
* are not needed than the inverse.
*
* NOTE: The iterator retains ownership of the RangedAnnotation objects that
* it returns and may modify them destructively to reuse them.
*
* The order of traversal is left-to-right by start index. Ranged annotations
* with the same start index may be returned in arbitrary order.
*
* @param start start of the range
* @param end end of the range
* @param keys key set to which to project the annotation set; null means all
* keys
*/
Iterable<RangedAnnotation<V>> rangedAnnotations(int start, int end, ReadableStringSet keys);
/**
* @return a set of all known keys in the annotation set
*/
ReadableStringSet knownKeys();
}