private IDocOp ComposeOperations(IDocOp op1, IDocOp op2) { _target = _defaultTarget; int op1Index = 0; int op2Index = 0; while (op1Index < op1.Size()) { op1.ApplyComponent(op1Index++, _target); while (_target.IsPostTarget()) { if (op2Index >= op2.Size()) { throw new OperationException("Document size mismatch: " + "op1 resulting length=" + DocOpUtil.ResultingDocumentLength(op1) + ", op2 initial length=" + DocOpUtil.InitialDocumentLength(op2)); } op2.ApplyComponent(op2Index++, _target); } } if (op2Index < op2.Size()) { _target = new FinisherPostTarget(); while (op2Index < op2.Size()) { op2.ApplyComponent(op2Index++, _target); } } FlushAnnotations(); return _normalizer.Finish(); }
/// <summary> /// Returns whether op is well-formed. /// /// Any violations recorded in the output <paramref name="collector"/> that are not well-formedness /// violations are meaningless. /// </summary> public static bool IsWellformed(ViolationCollector collector, IDocOp docOp) { if (docOp is IBufferedDocOp) { return IsWellformed(collector, (BufferedDocOp) docOp); } return IsWellformedRaw(collector, docOp); }
/// <summary> /// Same as <see cref="IsWellformed"/>, but without the fast path for <see cref="BufferedDocOp"/> /// </summary> private static bool IsWellformedRaw(ViolationCollector collector, IDocOp docOp) { // 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. var validationResult = Validate(collector, DocumentSchema.NoSchemaConstraints, DocOpAutomaton.EmptyDocument, docOp); return validationResult != ValidationResult.IllFormed; }
/// <summary> /// Returns the composition of two operations, without checking whether the result is ill-formed. /// </summary> /// <remarks> /// As mentioned in {@link UncheckedDocOpBuffer}, checked should only be used for testing or /// when performance is a concern. /// </remarks> /// <param name="first">the first operation</param> /// <param name="second">the second operation</param> /// <returns>the result of the composition</returns> /// <exception cref="OperationException">if applying op1 followed by op2 would be invalid.</exception> public static IDocOp ComposeUnchecked(IDocOp first, IDocOp second) { try { return new Composer(new UncheckedDocOpBuffer()).ComposeOperations(first, second); } catch (ComposeException exception) { throw new OperationException(exception.Message, exception); } }
private static ValidationResult Validate(ViolationCollector collector, IDocumentSchema schema, IAutomatonDocument document, IDocOp docOp) { if (schema == null) { schema = DocumentSchema.NoSchemaConstraints; } var automation = new DocOpAutomaton(document, schema); var accu = new ValidationResult[] { ValidationResult.Valid }; try { docOp.Apply(new ValidationDocOpCursor(collector, automation, accu)); } catch (IllFormedException illFormed) { return ValidationResult.IllFormed; } accu[0] = accu[0].MergeWith(automation.CheckFinish(collector)); return accu[0]; }
public BufferedDocInitialization(IDocOp op) { this._op = op; }
internal static string ToConciseString(IDocOp docOp) { var sb = new StringBuilder(); docOp.Apply(CreateConciseStringBuilder(docOp, sb)); return sb.ToString(); }
public static IDocOp Normalize(IDocOp input) { var normalizer = new AnnotationsNormalizer<IDocOp>(new RangeNormalizer<IDocOp>(new DocOpBuffer())); input.Apply(normalizer); return normalizer.Finish(); }
/// <summary> /// Computes the number of items of the document that an op applies to, prior to its application. /// </summary> public static int InitialDocumentLength(IDocOp docOp) { int[] size = { 0 }; docOp.Apply(new InitialDocumentLengthDocOpCursor(size)); return size[0]; }
/// <summary> /// Computes the number of items of the document that an op produces when applied. /// </summary> public static int ResultingDocumentLength(IDocOp docOp) { int[] size = { 0 }; docOp.Apply(new ResultingDocumentLengthDocOpCursor(size)); return size[0]; }
public SimpleDocOpCursor(IDocOp docOp, StringBuilder sb) { _docOp = docOp; _sb = sb; }
public static IDocInitialization AsInitialization(IDocOp docOp) { var docInitialization = docOp as IDocInitialization; if (docInitialization != null) { return docInitialization; } return new BufferedDocInitialization(docOp); }
private static IDocOpCursor CreateConciseStringBuilder(IDocOp docOp, StringBuilder sb) { return new SimpleDocOpCursor(docOp, sb); }
public BlipContentOperation(WaveletOperationContext context, IDocOp contentOp, UpdateContributorMethod update = UpdateContributorMethod.Add) : base(context) { ContentOp = contentOp; _method = update; }
/// <summary> /// Transforms a pair of operations. /// </summary> /// <param name="clientOperation">the operation from the client</param> /// <param name="serverOperation">the operation from the server</param> /// <returns>the transformed pair of operations</returns> /// <exception cref="TransformException">if a problem was encountered during the transformation process</exception> public static OperationPair<IDocOp> Transform(IDocOp clientOperation, IDocOp serverOperation) { // The transform process consists of decomposing the client and server // operations into two constituent operations each and performing four // transforms structured as in the following diagram: // ci0 cn0 // si0 si1 si2 // ci1 cn1 // sn0 sn1 sn2 // ci2 cn2 // try { Tuple<IDocOp, IDocOp> c = Decomposer.Decompose(clientOperation); Tuple<IDocOp, IDocOp> s = Decomposer.Decompose(serverOperation); var r1 = new InsertionTransformer().TransformOperations(c.Item1, s.Item1); var r2 = new InsertionNoninsertionTransformer().TransformOperations(r1.ClientOperation, s.Item2); var r3 = new InsertionNoninsertionTransformer().TransformOperations(r1.ServerOperation, c.Item2); var r4 = new NoninsertionTransformer().TransformOperations(r3.ServerOperation, r2.ServerOperation); return new OperationPair<IDocOp>( Composer.Compose(r2.ClientOperation, r4.ClientOperation), Composer.Compose(r3.ClientOperation, r4.ServerOperation)); } catch (OperationException e) { throw new TransformException(e.Message, e); } }