Package org.waveprotocol.wave.model.document.operation.impl

Source Code of org.waveprotocol.wave.model.document.operation.impl.DocOpValidator

/**
* 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.operation.impl;

import org.waveprotocol.wave.model.document.operation.AnnotationBoundaryMap;
import org.waveprotocol.wave.model.document.operation.Attributes;
import org.waveprotocol.wave.model.document.operation.AttributesUpdate;
import org.waveprotocol.wave.model.document.operation.DocInitialization;
import org.waveprotocol.wave.model.document.operation.DocOp;
import org.waveprotocol.wave.model.document.operation.DocOpCursor;
import org.waveprotocol.wave.model.document.operation.automaton.AutomatonDocument;
import org.waveprotocol.wave.model.document.operation.automaton.DocOpAutomaton;
import org.waveprotocol.wave.model.document.operation.automaton.DocumentSchema;
import org.waveprotocol.wave.model.document.operation.automaton.DocOpAutomaton.ValidationResult;
import org.waveprotocol.wave.model.document.operation.automaton.DocOpAutomaton.ViolationCollector;
import org.waveprotocol.wave.model.util.Preconditions;

/**
* Validates an operation against a document.
*
*
*/
public final class DocOpValidator {

  private DocOpValidator() {}

  /**
   * Returns whether op is a well-formed document initialization and satisfies
   * the given schema constraints.
   */
  public static ValidationResult validate(ViolationCollector v,
      DocumentSchema schema, DocInitialization op) {
    Preconditions.checkNotNull(schema, "Schema constraints required, if not, " +
        "use DocumentSchema.NO_SCHEMA_CONSTRAINTS");
    return validate(v, schema, DocOpAutomaton.EMPTY_DOCUMENT, op);
  }

  /**
   * Returns whether op is well-formed.
   *
   * Any violations recorded in the output v that are not well-formedness
   * violations are meaningless.
   */
  public static boolean isWellFormed(ViolationCollector v, DocOp op) {
    if (op instanceof BufferedDocOpImpl) {
      return isWellFormed(v, (BufferedDocOpImpl) op);
    } else {
      return isWellFormedRaw(v, op);
    }
  }

  /**
   * Same as {@link #isWellFormed(ViolationCollector, DocOp)}, but with
   * a fast path for already-validated instances of BufferedDocOpImpl
   */
  public static boolean isWellFormed(ViolationCollector v, BufferedDocOpImpl buffered) {
    if (buffered.isKnownToBeWellFormed()) {
      // fast path
      return true;
    } else {
      if (isWellFormedRaw(v, buffered)) {
        buffered.markWellFormed();
        return true;
      } else {
        return false;
      }
    }
  }

  /**
   * Same as {@link #isWellFormed(ViolationCollector, DocOp)}, but without
   * the fast path for BufferedDocOpImpl
   */
  public static boolean isWellFormedRaw(ViolationCollector v, DocOp op) {
    // We validate the operation against the empty document.  It will likely
    // be invalid; however, we ignore the validity aspect anyway since we
    // only care about well-formedness.
    return !validate(v, DocumentSchema.NO_SCHEMA_CONSTRAINTS,
        DocOpAutomaton.EMPTY_DOCUMENT, op)
        .isIllFormed();
  }

  private static final class IllFormed extends RuntimeException {
    IllFormed(String message) {
      super(message);
    }
    @Override
    public Throwable fillInStackTrace() {
      return this// don't fill in stack trace, for efficiency
    }
  }

  private static final IllFormed ILL_FORMED = new IllFormed(
      "Preallocated exception with a meaningless stack trace");

  /**
   * Returns whether op is well-formed, applies to doc, and preserves the given
   * schema constraints.  Will not modify doc.
   */
  public static <N, E extends N, T extends N> ValidationResult validate(
      final ViolationCollector v, DocumentSchema schema,
      AutomatonDocument doc, DocOp op) {

    if (schema == null) {
      schema = DocumentSchema.NO_SCHEMA_CONSTRAINTS;
    }
    final DocOpAutomaton a = new DocOpAutomaton(doc, schema);
    final ValidationResult[] accu = new ValidationResult[] { ValidationResult.VALID };
    try {
      op.apply(new DocOpCursor() {
        void abortIfIllFormed() {
          if (accu[0].isIllFormed()) {
            throw ILL_FORMED;
          }
        }

        @Override
        public void characters(String s) {
          accu[0] = accu[0].mergeWith(a.checkCharacters(s, v));
          abortIfIllFormed();
          a.doCharacters(s);
        }

        @Override
        public void deleteCharacters(String chars) {
          accu[0] = accu[0].mergeWith(a.checkDeleteCharacters(chars, v));
          abortIfIllFormed();
          a.doDeleteCharacters(chars);
        }

        @Override
        public void deleteElementEnd() {
          accu[0] = accu[0].mergeWith(a.checkDeleteElementEnd(v));
          abortIfIllFormed();
          a.doDeleteElementEnd();
        }

        @Override
        public void deleteElementStart(String type, Attributes attrs) {
          accu[0] = accu[0].mergeWith(a.checkDeleteElementStart(type, attrs, v));
          abortIfIllFormed();
          a.doDeleteElementStart(type, attrs);
        }

        @Override
        public void replaceAttributes(Attributes oldAttrs, Attributes newAttrs) {
          accu[0] = accu[0].mergeWith(a.checkReplaceAttributes(oldAttrs, newAttrs, v));
          abortIfIllFormed();
          a.doReplaceAttributes(oldAttrs, newAttrs);
        }

        @Override
        public void retain(int itemCount) {
          accu[0] = accu[0].mergeWith(a.checkRetain(itemCount, v));
          abortIfIllFormed();
          a.doRetain(itemCount);
        }

        @Override
        public void updateAttributes(AttributesUpdate u) {
          accu[0] = accu[0].mergeWith(a.checkUpdateAttributes(u, v));
          abortIfIllFormed();
          a.doUpdateAttributes(u);
        }

        @Override
        public void annotationBoundary(AnnotationBoundaryMap map) {
          accu[0] = accu[0].mergeWith(a.checkAnnotationBoundary(map, v));
          abortIfIllFormed();
          a.doAnnotationBoundary(map);
        }

        @Override
        public void elementEnd() {
          accu[0] = accu[0].mergeWith(a.checkElementEnd(v));
          abortIfIllFormed();
          a.doElementEnd();
        }

        @Override
        public void elementStart(String type, Attributes attrs) {
          accu[0] = accu[0].mergeWith(a.checkElementStart(type, attrs, v));
          abortIfIllFormed();
          a.doElementStart(type, attrs);
        }
      });
    } catch (IllFormed e) {
      return ValidationResult.ILL_FORMED;
    }
    accu[0] = accu[0].mergeWith(a.checkFinish(v));
    return accu[0];
  }

}
TOP

Related Classes of org.waveprotocol.wave.model.document.operation.impl.DocOpValidator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.