/**
* Copyright 2010 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.experimental.schema;
import org.waveprotocol.wave.model.document.operation.Attributes;
import org.waveprotocol.wave.model.document.operation.AttributesUpdate;
import java.util.AbstractList;
import java.util.List;
import java.util.Map;
/**
* A schema pattern.
*
*/
public final class SchemaPattern {
/**
* An entry in the prologue, containing an element type and a pattern.
*/
public static final class PrologueEntry {
private final String type;
private final SchemaPattern pattern;
PrologueEntry(String type, SchemaPattern pattern) {
this.type = type;
this.pattern = pattern;
}
String elementType() {
return type;
}
SchemaPattern pattern() {
return pattern;
}
}
// TODO(user): Change prologue implementation to prevent exponential space blowout attacks.
/**
* A prologue, containing a list of element patterns.
*/
public static final class Prologue extends AbstractList<PrologueEntry> {
private final List<PrologueEntry> entries;
/**
* The package-private constructor for constructing prologues.
*
* Warning: The entries list should not be modified after being used to
* construct this prologue. It is not defensively copied because this
* constructor is package-private.
*
* @param entries The list of element patterns that make up the prologue.
*/
Prologue(List<PrologueEntry> entries) {
this.entries = entries;
}
@Override
public PrologueEntry get(int index) {
return entries.get(index);
}
@Override
public int size() {
return entries.size();
}
}
private AttributesValidator attributesValidator;
private Prologue prologue;
private Map<String, SchemaPattern> potentialChildren;
private CharacterValidator characterValidator;
SchemaPattern() {}
void initialize(
AttributesValidator attributesValidator,
Prologue prologue,
Map<String, SchemaPattern> potentialChildren,
CharacterValidator characterValidator) {
// It should be impossible for the fields to be non-null at this point.
assert this.attributesValidator == null;
assert this.prologue == null;
assert this.potentialChildren == null;
assert this.characterValidator == null;
this.attributesValidator = attributesValidator;
this.prologue = prologue;
this.potentialChildren = potentialChildren;
this.characterValidator = characterValidator;
}
/**
* @return the prologue of this schema pattern
*/
public Prologue prologue() {
return prologue;
}
/**
* Returns the schema pattern corresponding to the given child element type.
*
* @param elementType the element type of a child
* @return the schema pattern the child should conform to
*/
public SchemaPattern child(String elementType) {
return potentialChildren.get(elementType);
}
/**
* Checks whether the given <code>Attributes</code> conforms to this schema
* pattern.
*
* @param attributes the <code>Attributes</code> to check
* @return the result of validating the <code>Attributes</code>
*/
public AttributeValidationResult validateAttributes(Attributes attributes) {
return attributesValidator.validate(attributes);
}
/**
* Checks whether the given <code>AttributesUpdate</code> conforms to this
* schema pattern.
*
* @param update the <code>AttributesUpdate</code> to check
* @return the result of validating the <code>AttributesUpdate</code>
*/
public AttributeValidationResult validateAttributesUpdate(AttributesUpdate update) {
return attributesValidator.validate(update);
}
/**
* Checks whether the given characters conform to this schema pattern.
*
* @param characters the characters to check
* @return -1 if the characters are all valid, or otherwise the number of
* valid Unicode characters before the first invalid character
*/
public int validateCharacters(String characters) {
return characterValidator.validate(characters);
}
}