1703 lines
		
	
	
	
		
			63 KiB
			
		
	
	
	
		
			Diff
		
	
	
	
	
	
		
		
			
		
	
	
			1703 lines
		
	
	
	
		
			63 KiB
			
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 
								 | 
							
								From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
							 | 
						||
| 
								 | 
							
								From: Jake Potrebic <jake.m.potrebic@gmail.com>
							 | 
						||
| 
								 | 
							
								Date: Sat, 1 Jan 2022 21:24:50 -0800
							 | 
						||
| 
								 | 
							
								Subject: [PATCH] Fix saving configs with more long comments
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This is a bug with snakeyaml
							 | 
						||
| 
								 | 
							
								PR: https://bitbucket.org/snakeyaml/snakeyaml/pull-requests/3
							 | 
						||
| 
								 | 
							
								Issue: https://bitbucket.org/snakeyaml/snakeyaml/issues/518/comments-could-cause-queue-full
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Added the entire Emitter class from snakeyaml because
							 | 
						||
| 
								 | 
							
								dev-imports doesn't work with non-mojang-added dependencies
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Replacement for upstream: https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/commits/a7505b3cd0498baca152777767f0e4ddebbe4d1a
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								diff --git a/src/main/java/org/yaml/snakeyaml/emitter/Emitter.java b/src/main/java/org/yaml/snakeyaml/emitter/Emitter.java
							 | 
						||
| 
								 | 
							
								new file mode 100644
							 | 
						||
| 
								 | 
							
								index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
							 | 
						||
| 
								 | 
							
								--- /dev/null
							 | 
						||
| 
								 | 
							
								+++ b/src/main/java/org/yaml/snakeyaml/emitter/Emitter.java
							 | 
						||
| 
								 | 
							
								@@ -0,0 +0,0 @@
							 | 
						||
| 
								 | 
							
								+/**
							 | 
						||
| 
								 | 
							
								+ * Copyright (c) 2008, SnakeYAML
							 | 
						||
| 
								 | 
							
								+ *
							 | 
						||
| 
								 | 
							
								+ * 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.yaml.snakeyaml.emitter;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.DumperOptions;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.DumperOptions.ScalarStyle;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.DumperOptions.Version;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.comments.CommentEventsCollector;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.comments.CommentLine;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.comments.CommentType;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.error.YAMLException;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.AliasEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.CollectionEndEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.CollectionStartEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.CommentEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.DocumentEndEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.DocumentStartEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.Event;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.Event.ID;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.MappingEndEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.MappingStartEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.NodeEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.ScalarEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.SequenceEndEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.SequenceStartEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.StreamEndEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.events.StreamStartEvent;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.nodes.Tag;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.reader.StreamReader;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.scanner.Constant;
							 | 
						||
| 
								 | 
							
								+import org.yaml.snakeyaml.util.ArrayStack;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+import java.io.IOException;
							 | 
						||
| 
								 | 
							
								+import java.io.Writer;
							 | 
						||
| 
								 | 
							
								+import java.util.ArrayDeque;
							 | 
						||
| 
								 | 
							
								+import java.util.HashMap;
							 | 
						||
| 
								 | 
							
								+import java.util.HashSet;
							 | 
						||
| 
								 | 
							
								+import java.util.Iterator;
							 | 
						||
| 
								 | 
							
								+import java.util.LinkedHashMap;
							 | 
						||
| 
								 | 
							
								+import java.util.List;
							 | 
						||
| 
								 | 
							
								+import java.util.Map;
							 | 
						||
| 
								 | 
							
								+import java.util.Queue;
							 | 
						||
| 
								 | 
							
								+import java.util.Set;
							 | 
						||
| 
								 | 
							
								+import java.util.TreeSet;
							 | 
						||
| 
								 | 
							
								+import java.util.concurrent.ArrayBlockingQueue;
							 | 
						||
| 
								 | 
							
								+import java.util.regex.Matcher;
							 | 
						||
| 
								 | 
							
								+import java.util.regex.Pattern;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+/**
							 | 
						||
| 
								 | 
							
								+ * <pre>
							 | 
						||
| 
								 | 
							
								+ * Emitter expects events obeying the following grammar:
							 | 
						||
| 
								 | 
							
								+ * stream ::= STREAM-START document* STREAM-END
							 | 
						||
| 
								 | 
							
								+ * document ::= DOCUMENT-START node DOCUMENT-END
							 | 
						||
| 
								 | 
							
								+ * node ::= SCALAR | sequence | mapping
							 | 
						||
| 
								 | 
							
								+ * sequence ::= SEQUENCE-START node* SEQUENCE-END
							 | 
						||
| 
								 | 
							
								+ * mapping ::= MAPPING-START (node node)* MAPPING-END
							 | 
						||
| 
								 | 
							
								+ * </pre>
							 | 
						||
| 
								 | 
							
								+ */
							 | 
						||
| 
								 | 
							
								+public final class Emitter implements Emitable {
							 | 
						||
| 
								 | 
							
								+    public static final int MIN_INDENT = 1;
							 | 
						||
| 
								 | 
							
								+    public static final int MAX_INDENT = 10;
							 | 
						||
| 
								 | 
							
								+    private static final char[] SPACE = {' '};
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private static final Pattern SPACES_PATTERN = Pattern.compile("\\s");
							 | 
						||
| 
								 | 
							
								+    private static final Set<Character> INVALID_ANCHOR = new HashSet();
							 | 
						||
| 
								 | 
							
								+    static {
							 | 
						||
| 
								 | 
							
								+        INVALID_ANCHOR.add('[');
							 | 
						||
| 
								 | 
							
								+        INVALID_ANCHOR.add(']');
							 | 
						||
| 
								 | 
							
								+        INVALID_ANCHOR.add('{');
							 | 
						||
| 
								 | 
							
								+        INVALID_ANCHOR.add('}');
							 | 
						||
| 
								 | 
							
								+        INVALID_ANCHOR.add(',');
							 | 
						||
| 
								 | 
							
								+        INVALID_ANCHOR.add('*');
							 | 
						||
| 
								 | 
							
								+        INVALID_ANCHOR.add('&');
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private static final Map<Character, String> ESCAPE_REPLACEMENTS = new HashMap<Character, String>();
							 | 
						||
| 
								 | 
							
								+    static {
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\0', "0");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u0007', "a");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u0008', "b");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u0009', "t");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\n', "n");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u000B', "v");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u000C', "f");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\r', "r");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u001B', "e");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('"', "\"");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\\', "\\");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u0085', "N");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u00A0', "_");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u2028', "L");
							 | 
						||
| 
								 | 
							
								+        ESCAPE_REPLACEMENTS.put('\u2029', "P");
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private final static Map<String, String> DEFAULT_TAG_PREFIXES = new LinkedHashMap<String, String>();
							 | 
						||
| 
								 | 
							
								+    static {
							 | 
						||
| 
								 | 
							
								+        DEFAULT_TAG_PREFIXES.put("!", "!");
							 | 
						||
| 
								 | 
							
								+        DEFAULT_TAG_PREFIXES.put(Tag.PREFIX, "!!");
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+    // The stream should have the methods `write` and possibly `flush`.
							 | 
						||
| 
								 | 
							
								+    private final Writer stream;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Encoding is defined by Writer (cannot be overridden by STREAM-START.)
							 | 
						||
| 
								 | 
							
								+    // private Charset encoding;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Emitter is a state machine with a stack of states to handle nested
							 | 
						||
| 
								 | 
							
								+    // structures.
							 | 
						||
| 
								 | 
							
								+    private final ArrayStack<EmitterState> states;
							 | 
						||
| 
								 | 
							
								+    private EmitterState state;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Current event and the event queue.
							 | 
						||
| 
								 | 
							
								+    private final Queue<Event> events;
							 | 
						||
| 
								 | 
							
								+    private Event event;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // The current indentation level and the stack of previous indents.
							 | 
						||
| 
								 | 
							
								+    private final ArrayStack<Integer> indents;
							 | 
						||
| 
								 | 
							
								+    private Integer indent;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Flow level.
							 | 
						||
| 
								 | 
							
								+    private int flowLevel;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Contexts.
							 | 
						||
| 
								 | 
							
								+    private boolean rootContext;
							 | 
						||
| 
								 | 
							
								+    private boolean mappingContext;
							 | 
						||
| 
								 | 
							
								+    private boolean simpleKeyContext;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    //
							 | 
						||
| 
								 | 
							
								+    // Characteristics of the last emitted character:
							 | 
						||
| 
								 | 
							
								+    // - current position.
							 | 
						||
| 
								 | 
							
								+    // - is it a whitespace?
							 | 
						||
| 
								 | 
							
								+    // - is it an indention character
							 | 
						||
| 
								 | 
							
								+    // (indentation space, '-', '?', or ':')?
							 | 
						||
| 
								 | 
							
								+    // private int line; this variable is not used
							 | 
						||
| 
								 | 
							
								+    private int column;
							 | 
						||
| 
								 | 
							
								+    private boolean whitespace;
							 | 
						||
| 
								 | 
							
								+    private boolean indention;
							 | 
						||
| 
								 | 
							
								+    private boolean openEnded;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Formatting details.
							 | 
						||
| 
								 | 
							
								+    private final Boolean canonical;
							 | 
						||
| 
								 | 
							
								+    // pretty print flow by adding extra line breaks
							 | 
						||
| 
								 | 
							
								+    private final Boolean prettyFlow;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private final boolean allowUnicode;
							 | 
						||
| 
								 | 
							
								+    private int bestIndent;
							 | 
						||
| 
								 | 
							
								+    private final int indicatorIndent;
							 | 
						||
| 
								 | 
							
								+    private final boolean indentWithIndicator;
							 | 
						||
| 
								 | 
							
								+    private int bestWidth;
							 | 
						||
| 
								 | 
							
								+    private final char[] bestLineBreak;
							 | 
						||
| 
								 | 
							
								+    private final boolean splitLines;
							 | 
						||
| 
								 | 
							
								+    private final int maxSimpleKeyLength;
							 | 
						||
| 
								 | 
							
								+    private final boolean emitComments;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Tag prefixes.
							 | 
						||
| 
								 | 
							
								+    private Map<String, String> tagPrefixes;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Prepared anchor and tag.
							 | 
						||
| 
								 | 
							
								+    private String preparedAnchor;
							 | 
						||
| 
								 | 
							
								+    private String preparedTag;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Scalar analysis and style.
							 | 
						||
| 
								 | 
							
								+    private ScalarAnalysis analysis;
							 | 
						||
| 
								 | 
							
								+    private DumperOptions.ScalarStyle style;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Comment processing
							 | 
						||
| 
								 | 
							
								+    private final CommentEventsCollector blockCommentsCollector;
							 | 
						||
| 
								 | 
							
								+    private final CommentEventsCollector inlineCommentsCollector;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    public Emitter(Writer stream, DumperOptions opts) {
							 | 
						||
| 
								 | 
							
								+        // The stream should have the methods `write` and possibly `flush`.
							 | 
						||
| 
								 | 
							
								+        this.stream = stream;
							 | 
						||
| 
								 | 
							
								+        // Emitter is a state machine with a stack of states to handle nested
							 | 
						||
| 
								 | 
							
								+        // structures.
							 | 
						||
| 
								 | 
							
								+        this.states = new ArrayStack<EmitterState>(100);
							 | 
						||
| 
								 | 
							
								+        this.state = new ExpectStreamStart();
							 | 
						||
| 
								 | 
							
								+        // Current event and the event queue.
							 | 
						||
| 
								 | 
							
								+        this.events = new ArrayDeque<>(100); // Paper - allow more than 100 events (or comments)
							 | 
						||
| 
								 | 
							
								+        // this.events = new ArrayBlockingQueue<>(100);
							 | 
						||
| 
								 | 
							
								+        this.event = null;
							 | 
						||
| 
								 | 
							
								+        // The current indentation level and the stack of previous indents.
							 | 
						||
| 
								 | 
							
								+        this.indents = new ArrayStack<Integer>(10);
							 | 
						||
| 
								 | 
							
								+        this.indent = null;
							 | 
						||
| 
								 | 
							
								+        // Flow level.
							 | 
						||
| 
								 | 
							
								+        this.flowLevel = 0;
							 | 
						||
| 
								 | 
							
								+        // Contexts.
							 | 
						||
| 
								 | 
							
								+        mappingContext = false;
							 | 
						||
| 
								 | 
							
								+        simpleKeyContext = false;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        //
							 | 
						||
| 
								 | 
							
								+        // Characteristics of the last emitted character:
							 | 
						||
| 
								 | 
							
								+        // - current position.
							 | 
						||
| 
								 | 
							
								+        // - is it a whitespace?
							 | 
						||
| 
								 | 
							
								+        // - is it an indention character
							 | 
						||
| 
								 | 
							
								+        // (indentation space, '-', '?', or ':')?
							 | 
						||
| 
								 | 
							
								+        column = 0;
							 | 
						||
| 
								 | 
							
								+        whitespace = true;
							 | 
						||
| 
								 | 
							
								+        indention = true;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // Whether the document requires an explicit document indicator
							 | 
						||
| 
								 | 
							
								+        openEnded = false;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // Formatting details.
							 | 
						||
| 
								 | 
							
								+        this.canonical = opts.isCanonical();
							 | 
						||
| 
								 | 
							
								+        this.prettyFlow = opts.isPrettyFlow();
							 | 
						||
| 
								 | 
							
								+        this.allowUnicode = opts.isAllowUnicode();
							 | 
						||
| 
								 | 
							
								+        this.bestIndent = 2;
							 | 
						||
| 
								 | 
							
								+        if ((opts.getIndent() > MIN_INDENT) && (opts.getIndent() < MAX_INDENT)) {
							 | 
						||
| 
								 | 
							
								+            this.bestIndent = opts.getIndent();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        this.indicatorIndent = opts.getIndicatorIndent();
							 | 
						||
| 
								 | 
							
								+        this.indentWithIndicator = opts.getIndentWithIndicator();
							 | 
						||
| 
								 | 
							
								+        this.bestWidth = 80;
							 | 
						||
| 
								 | 
							
								+        if (opts.getWidth() > this.bestIndent * 2) {
							 | 
						||
| 
								 | 
							
								+            this.bestWidth = opts.getWidth();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        this.bestLineBreak = opts.getLineBreak().getString().toCharArray();
							 | 
						||
| 
								 | 
							
								+        this.splitLines = opts.getSplitLines();
							 | 
						||
| 
								 | 
							
								+        this.maxSimpleKeyLength = opts.getMaxSimpleKeyLength();
							 | 
						||
| 
								 | 
							
								+        this.emitComments = opts.isProcessComments();
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // Tag prefixes.
							 | 
						||
| 
								 | 
							
								+        this.tagPrefixes = new LinkedHashMap<String, String>();
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // Prepared anchor and tag.
							 | 
						||
| 
								 | 
							
								+        this.preparedAnchor = null;
							 | 
						||
| 
								 | 
							
								+        this.preparedTag = null;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // Scalar analysis and style.
							 | 
						||
| 
								 | 
							
								+        this.analysis = null;
							 | 
						||
| 
								 | 
							
								+        this.style = null;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // Comment processing
							 | 
						||
| 
								 | 
							
								+        this.blockCommentsCollector = new CommentEventsCollector(events,
							 | 
						||
| 
								 | 
							
								+            CommentType.BLANK_LINE, CommentType.BLOCK);
							 | 
						||
| 
								 | 
							
								+        this.inlineCommentsCollector = new CommentEventsCollector(events,
							 | 
						||
| 
								 | 
							
								+            CommentType.IN_LINE);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    public void emit(Event event) throws IOException {
							 | 
						||
| 
								 | 
							
								+        this.events.add(event);
							 | 
						||
| 
								 | 
							
								+        while (!needMoreEvents()) {
							 | 
						||
| 
								 | 
							
								+            this.event = this.events.poll();
							 | 
						||
| 
								 | 
							
								+            this.state.expect();
							 | 
						||
| 
								 | 
							
								+            this.event = null;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // In some cases, we wait for a few next events before emitting.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean needMoreEvents() {
							 | 
						||
| 
								 | 
							
								+        if (events.isEmpty()) {
							 | 
						||
| 
								 | 
							
								+            return true;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        Iterator<Event> iter = events.iterator();
							 | 
						||
| 
								 | 
							
								+        Event event = iter.next(); // FIXME why without check ???
							 | 
						||
| 
								 | 
							
								+        while(event instanceof CommentEvent) {
							 | 
						||
| 
								 | 
							
								+            if (!iter.hasNext()) {
							 | 
						||
| 
								 | 
							
								+                return true;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            event = iter.next();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        if (event instanceof DocumentStartEvent) {
							 | 
						||
| 
								 | 
							
								+            return needEvents(iter, 1);
							 | 
						||
| 
								 | 
							
								+        } else if (event instanceof SequenceStartEvent) {
							 | 
						||
| 
								 | 
							
								+            return needEvents(iter, 2);
							 | 
						||
| 
								 | 
							
								+        } else if (event instanceof MappingStartEvent) {
							 | 
						||
| 
								 | 
							
								+            return needEvents(iter, 3);
							 | 
						||
| 
								 | 
							
								+        } else if (event instanceof StreamStartEvent) {
							 | 
						||
| 
								 | 
							
								+            return needEvents(iter, 2);
							 | 
						||
| 
								 | 
							
								+        } else if (event instanceof StreamEndEvent) {
							 | 
						||
| 
								 | 
							
								+            return false;
							 | 
						||
| 
								 | 
							
								+        } else if (emitComments) {
							 | 
						||
| 
								 | 
							
								+            return needEvents(iter, 1);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return false;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean needEvents(Iterator<Event> iter, int count) {
							 | 
						||
| 
								 | 
							
								+        int level = 0;
							 | 
						||
| 
								 | 
							
								+        int actualCount = 0;
							 | 
						||
| 
								 | 
							
								+        while (iter.hasNext()) {
							 | 
						||
| 
								 | 
							
								+            Event event = iter.next();
							 | 
						||
| 
								 | 
							
								+            if (event instanceof CommentEvent) {
							 | 
						||
| 
								 | 
							
								+                continue;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            actualCount++;
							 | 
						||
| 
								 | 
							
								+            if (event instanceof DocumentStartEvent || event instanceof CollectionStartEvent) {
							 | 
						||
| 
								 | 
							
								+                level++;
							 | 
						||
| 
								 | 
							
								+            } else if (event instanceof DocumentEndEvent || event instanceof CollectionEndEvent) {
							 | 
						||
| 
								 | 
							
								+                level--;
							 | 
						||
| 
								 | 
							
								+            } else if (event instanceof StreamEndEvent) {
							 | 
						||
| 
								 | 
							
								+                level = -1;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (level < 0) {
							 | 
						||
| 
								 | 
							
								+                return false;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return actualCount < count;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void increaseIndent(boolean flow, boolean indentless) {
							 | 
						||
| 
								 | 
							
								+        indents.push(indent);
							 | 
						||
| 
								 | 
							
								+        if (indent == null) {
							 | 
						||
| 
								 | 
							
								+            if (flow) {
							 | 
						||
| 
								 | 
							
								+                indent = bestIndent;
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                indent = 0;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        } else if (!indentless) {
							 | 
						||
| 
								 | 
							
								+            this.indent += bestIndent;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // States
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Stream handlers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectStreamStart implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            if (event instanceof StreamStartEvent) {
							 | 
						||
| 
								 | 
							
								+                writeStreamStart();
							 | 
						||
| 
								 | 
							
								+                state = new ExpectFirstDocumentStart();
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                throw new EmitterException("expected StreamStartEvent, but got " + event);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectNothing implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("expecting nothing, but got " + event);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Document handlers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFirstDocumentStart implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            new ExpectDocumentStart(true).expect();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectDocumentStart implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        private final boolean first;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        public ExpectDocumentStart(boolean first) {
							 | 
						||
| 
								 | 
							
								+            this.first = first;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            if (event instanceof DocumentStartEvent) {
							 | 
						||
| 
								 | 
							
								+                DocumentStartEvent ev = (DocumentStartEvent) event;
							 | 
						||
| 
								 | 
							
								+                if ((ev.getVersion() != null || ev.getTags() != null) && openEnded) {
							 | 
						||
| 
								 | 
							
								+                    writeIndicator("...", true, false, false);
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (ev.getVersion() != null) {
							 | 
						||
| 
								 | 
							
								+                    String versionText = prepareVersion(ev.getVersion());
							 | 
						||
| 
								 | 
							
								+                    writeVersionDirective(versionText);
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                tagPrefixes = new LinkedHashMap<String, String>(DEFAULT_TAG_PREFIXES);
							 | 
						||
| 
								 | 
							
								+                if (ev.getTags() != null) {
							 | 
						||
| 
								 | 
							
								+                    Set<String> handles = new TreeSet<String>(ev.getTags().keySet());
							 | 
						||
| 
								 | 
							
								+                    for (String handle : handles) {
							 | 
						||
| 
								 | 
							
								+                        String prefix = ev.getTags().get(handle);
							 | 
						||
| 
								 | 
							
								+                        tagPrefixes.put(prefix, handle);
							 | 
						||
| 
								 | 
							
								+                        String handleText = prepareTagHandle(handle);
							 | 
						||
| 
								 | 
							
								+                        String prefixText = prepareTagPrefix(prefix);
							 | 
						||
| 
								 | 
							
								+                        writeTagDirective(handleText, prefixText);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                boolean implicit = first && !ev.getExplicit() && !canonical
							 | 
						||
| 
								 | 
							
								+                    && ev.getVersion() == null
							 | 
						||
| 
								 | 
							
								+                    && (ev.getTags() == null || ev.getTags().isEmpty())
							 | 
						||
| 
								 | 
							
								+                    && !checkEmptyDocument();
							 | 
						||
| 
								 | 
							
								+                if (!implicit) {
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                    writeIndicator("---", true, false, false);
							 | 
						||
| 
								 | 
							
								+                    if (canonical) {
							 | 
						||
| 
								 | 
							
								+                        writeIndent();
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                state = new ExpectDocumentRoot();
							 | 
						||
| 
								 | 
							
								+            } else if (event instanceof StreamEndEvent) {
							 | 
						||
| 
								 | 
							
								+                writeStreamEnd();
							 | 
						||
| 
								 | 
							
								+                state = new ExpectNothing();
							 | 
						||
| 
								 | 
							
								+            } else if (event instanceof CommentEvent) {
							 | 
						||
| 
								 | 
							
								+                blockCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+                writeBlockComment();
							 | 
						||
| 
								 | 
							
								+                // state = state; remains unchanged
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                throw new EmitterException("expected DocumentStartEvent, but got " + event);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectDocumentEnd implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            event = blockCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            writeBlockComment();
							 | 
						||
| 
								 | 
							
								+            if (event instanceof DocumentEndEvent) {
							 | 
						||
| 
								 | 
							
								+                writeIndent();
							 | 
						||
| 
								 | 
							
								+                if (((DocumentEndEvent) event).getExplicit()) {
							 | 
						||
| 
								 | 
							
								+                    writeIndicator("...", true, false, false);
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                flushStream();
							 | 
						||
| 
								 | 
							
								+                state = new ExpectDocumentStart(false);
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                throw new EmitterException("expected DocumentEndEvent, but got " + event);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectDocumentRoot implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            event = blockCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            if (!blockCommentsCollector.isEmpty()) {
							 | 
						||
| 
								 | 
							
								+                writeBlockComment();
							 | 
						||
| 
								 | 
							
								+                if (event instanceof DocumentEndEvent) {
							 | 
						||
| 
								 | 
							
								+                    new ExpectDocumentEnd().expect();
							 | 
						||
| 
								 | 
							
								+                    return;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            states.push(new ExpectDocumentEnd());
							 | 
						||
| 
								 | 
							
								+            expectNode(true, false, false);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Node handlers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void expectNode(boolean root, boolean mapping, boolean simpleKey) throws IOException {
							 | 
						||
| 
								 | 
							
								+        rootContext = root;
							 | 
						||
| 
								 | 
							
								+        mappingContext = mapping;
							 | 
						||
| 
								 | 
							
								+        simpleKeyContext = simpleKey;
							 | 
						||
| 
								 | 
							
								+        if (event instanceof AliasEvent) {
							 | 
						||
| 
								 | 
							
								+            expectAlias();
							 | 
						||
| 
								 | 
							
								+        } else if (event instanceof ScalarEvent || event instanceof CollectionStartEvent) {
							 | 
						||
| 
								 | 
							
								+            processAnchor("&");
							 | 
						||
| 
								 | 
							
								+            processTag();
							 | 
						||
| 
								 | 
							
								+            if (event instanceof ScalarEvent) {
							 | 
						||
| 
								 | 
							
								+                expectScalar();
							 | 
						||
| 
								 | 
							
								+            } else if (event instanceof SequenceStartEvent) {
							 | 
						||
| 
								 | 
							
								+                if (flowLevel != 0 || canonical || ((SequenceStartEvent) event).isFlow()
							 | 
						||
| 
								 | 
							
								+                    || checkEmptySequence()) {
							 | 
						||
| 
								 | 
							
								+                    expectFlowSequence();
							 | 
						||
| 
								 | 
							
								+                } else {
							 | 
						||
| 
								 | 
							
								+                    expectBlockSequence();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else {// MappingStartEvent
							 | 
						||
| 
								 | 
							
								+                if (flowLevel != 0 || canonical || ((MappingStartEvent) event).isFlow()
							 | 
						||
| 
								 | 
							
								+                    || checkEmptyMapping()) {
							 | 
						||
| 
								 | 
							
								+                    expectFlowMapping();
							 | 
						||
| 
								 | 
							
								+                } else {
							 | 
						||
| 
								 | 
							
								+                    expectBlockMapping();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        } else {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("expected NodeEvent, but got " + event);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void expectAlias() throws IOException {
							 | 
						||
| 
								 | 
							
								+        if (!(event instanceof AliasEvent)) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("Alias must be provided");
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        processAnchor("*");
							 | 
						||
| 
								 | 
							
								+        state = states.pop();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void expectScalar() throws IOException {
							 | 
						||
| 
								 | 
							
								+        increaseIndent(true, false);
							 | 
						||
| 
								 | 
							
								+        processScalar();
							 | 
						||
| 
								 | 
							
								+        indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+        state = states.pop();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Flow sequence handlers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void expectFlowSequence() throws IOException {
							 | 
						||
| 
								 | 
							
								+        writeIndicator("[", true, true, false);
							 | 
						||
| 
								 | 
							
								+        flowLevel++;
							 | 
						||
| 
								 | 
							
								+        increaseIndent(true, false);
							 | 
						||
| 
								 | 
							
								+        if (prettyFlow) {
							 | 
						||
| 
								 | 
							
								+            writeIndent();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        state = new ExpectFirstFlowSequenceItem();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFirstFlowSequenceItem implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            if (event instanceof SequenceEndEvent) {
							 | 
						||
| 
								 | 
							
								+                indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+                flowLevel--;
							 | 
						||
| 
								 | 
							
								+                writeIndicator("]", false, false, false);
							 | 
						||
| 
								 | 
							
								+                inlineCommentsCollector.collectEvents();
							 | 
						||
| 
								 | 
							
								+                writeInlineComments();
							 | 
						||
| 
								 | 
							
								+                state = states.pop();
							 | 
						||
| 
								 | 
							
								+            } else if (event instanceof CommentEvent) {
							 | 
						||
| 
								 | 
							
								+                blockCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+                writeBlockComment();
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                if (canonical || (column > bestWidth && splitLines) || prettyFlow) {
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                states.push(new ExpectFlowSequenceItem());
							 | 
						||
| 
								 | 
							
								+                expectNode(false, false, false);
							 | 
						||
| 
								 | 
							
								+                event = inlineCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+                writeInlineComments();
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFlowSequenceItem implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            if (event instanceof SequenceEndEvent) {
							 | 
						||
| 
								 | 
							
								+                indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+                flowLevel--;
							 | 
						||
| 
								 | 
							
								+                if (canonical) {
							 | 
						||
| 
								 | 
							
								+                    writeIndicator(",", false, false, false);
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                } else if (prettyFlow) {
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                writeIndicator("]", false, false, false);
							 | 
						||
| 
								 | 
							
								+                inlineCommentsCollector.collectEvents();
							 | 
						||
| 
								 | 
							
								+                writeInlineComments();
							 | 
						||
| 
								 | 
							
								+                if (prettyFlow) {
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                state = states.pop();
							 | 
						||
| 
								 | 
							
								+            } else if (event instanceof CommentEvent) {
							 | 
						||
| 
								 | 
							
								+                event = blockCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                writeIndicator(",", false, false, false);
							 | 
						||
| 
								 | 
							
								+                writeBlockComment();
							 | 
						||
| 
								 | 
							
								+                if (canonical || (column > bestWidth && splitLines) || prettyFlow) {
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                states.push(new ExpectFlowSequenceItem());
							 | 
						||
| 
								 | 
							
								+                expectNode(false, false, false);
							 | 
						||
| 
								 | 
							
								+                event = inlineCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+                writeInlineComments();
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Flow mapping handlers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void expectFlowMapping() throws IOException {
							 | 
						||
| 
								 | 
							
								+        writeIndicator("{", true, true, false);
							 | 
						||
| 
								 | 
							
								+        flowLevel++;
							 | 
						||
| 
								 | 
							
								+        increaseIndent(true, false);
							 | 
						||
| 
								 | 
							
								+        if (prettyFlow) {
							 | 
						||
| 
								 | 
							
								+            writeIndent();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        state = new ExpectFirstFlowMappingKey();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFirstFlowMappingKey implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            event = blockCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            writeBlockComment();
							 | 
						||
| 
								 | 
							
								+            if (event instanceof MappingEndEvent) {
							 | 
						||
| 
								 | 
							
								+                indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+                flowLevel--;
							 | 
						||
| 
								 | 
							
								+                writeIndicator("}", false, false, false);
							 | 
						||
| 
								 | 
							
								+                inlineCommentsCollector.collectEvents();
							 | 
						||
| 
								 | 
							
								+                writeInlineComments();
							 | 
						||
| 
								 | 
							
								+                state = states.pop();
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                if (canonical || (column > bestWidth && splitLines) || prettyFlow) {
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (!canonical && checkSimpleKey()) {
							 | 
						||
| 
								 | 
							
								+                    states.push(new ExpectFlowMappingSimpleValue());
							 | 
						||
| 
								 | 
							
								+                    expectNode(false, true, true);
							 | 
						||
| 
								 | 
							
								+                } else {
							 | 
						||
| 
								 | 
							
								+                    writeIndicator("?", true, false, false);
							 | 
						||
| 
								 | 
							
								+                    states.push(new ExpectFlowMappingValue());
							 | 
						||
| 
								 | 
							
								+                    expectNode(false, true, false);
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFlowMappingKey implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            if (event instanceof MappingEndEvent) {
							 | 
						||
| 
								 | 
							
								+                indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+                flowLevel--;
							 | 
						||
| 
								 | 
							
								+                if (canonical) {
							 | 
						||
| 
								 | 
							
								+                    writeIndicator(",", false, false, false);
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (prettyFlow) {
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                writeIndicator("}", false, false, false);
							 | 
						||
| 
								 | 
							
								+                inlineCommentsCollector.collectEvents();
							 | 
						||
| 
								 | 
							
								+                writeInlineComments();
							 | 
						||
| 
								 | 
							
								+                state = states.pop();
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                writeIndicator(",", false, false, false);
							 | 
						||
| 
								 | 
							
								+                event = blockCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+                writeBlockComment();
							 | 
						||
| 
								 | 
							
								+                if (canonical || (column > bestWidth && splitLines) || prettyFlow) {
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (!canonical && checkSimpleKey()) {
							 | 
						||
| 
								 | 
							
								+                    states.push(new ExpectFlowMappingSimpleValue());
							 | 
						||
| 
								 | 
							
								+                    expectNode(false, true, true);
							 | 
						||
| 
								 | 
							
								+                } else {
							 | 
						||
| 
								 | 
							
								+                    writeIndicator("?", true, false, false);
							 | 
						||
| 
								 | 
							
								+                    states.push(new ExpectFlowMappingValue());
							 | 
						||
| 
								 | 
							
								+                    expectNode(false, true, false);
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFlowMappingSimpleValue implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            writeIndicator(":", false, false, false);
							 | 
						||
| 
								 | 
							
								+            event = inlineCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            writeInlineComments();
							 | 
						||
| 
								 | 
							
								+            states.push(new ExpectFlowMappingKey());
							 | 
						||
| 
								 | 
							
								+            expectNode(false, true, false);
							 | 
						||
| 
								 | 
							
								+            inlineCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+            writeInlineComments();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFlowMappingValue implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            if (canonical || (column > bestWidth) || prettyFlow) {
							 | 
						||
| 
								 | 
							
								+                writeIndent();
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            writeIndicator(":", true, false, false);
							 | 
						||
| 
								 | 
							
								+            event = inlineCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            writeInlineComments();
							 | 
						||
| 
								 | 
							
								+            states.push(new ExpectFlowMappingKey());
							 | 
						||
| 
								 | 
							
								+            expectNode(false, true, false);
							 | 
						||
| 
								 | 
							
								+            inlineCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+            writeInlineComments();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Block sequence handlers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void expectBlockSequence() throws IOException {
							 | 
						||
| 
								 | 
							
								+        boolean indentless = mappingContext && !indention;
							 | 
						||
| 
								 | 
							
								+        increaseIndent(false, indentless);
							 | 
						||
| 
								 | 
							
								+        state = new ExpectFirstBlockSequenceItem();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFirstBlockSequenceItem implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            new ExpectBlockSequenceItem(true).expect();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectBlockSequenceItem implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        private final boolean first;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        public ExpectBlockSequenceItem(boolean first) {
							 | 
						||
| 
								 | 
							
								+            this.first = first;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            if (!this.first && event instanceof SequenceEndEvent) {
							 | 
						||
| 
								 | 
							
								+                indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+                state = states.pop();
							 | 
						||
| 
								 | 
							
								+            } else if( event instanceof CommentEvent) {
							 | 
						||
| 
								 | 
							
								+                blockCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                writeIndent();
							 | 
						||
| 
								 | 
							
								+                if (!indentWithIndicator || this.first) {
							 | 
						||
| 
								 | 
							
								+                    writeWhitespace(indicatorIndent);
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                writeIndicator("-", true, false, true);
							 | 
						||
| 
								 | 
							
								+                if (indentWithIndicator && this.first) {
							 | 
						||
| 
								 | 
							
								+                    indent += indicatorIndent;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (!blockCommentsCollector.isEmpty()) {
							 | 
						||
| 
								 | 
							
								+                    increaseIndent(false, false);
							 | 
						||
| 
								 | 
							
								+                    writeBlockComment();
							 | 
						||
| 
								 | 
							
								+                    if(event instanceof ScalarEvent) {
							 | 
						||
| 
								 | 
							
								+                        analysis = analyzeScalar(((ScalarEvent)event).getValue());
							 | 
						||
| 
								 | 
							
								+                        if (!analysis.isEmpty()) {
							 | 
						||
| 
								 | 
							
								+                            writeIndent();
							 | 
						||
| 
								 | 
							
								+                        }
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                states.push(new ExpectBlockSequenceItem(false));
							 | 
						||
| 
								 | 
							
								+                expectNode(false, false, false);
							 | 
						||
| 
								 | 
							
								+                inlineCommentsCollector.collectEvents();
							 | 
						||
| 
								 | 
							
								+                writeInlineComments();
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Block mapping handlers.
							 | 
						||
| 
								 | 
							
								+    private void expectBlockMapping() throws IOException {
							 | 
						||
| 
								 | 
							
								+        increaseIndent(false, false);
							 | 
						||
| 
								 | 
							
								+        state = new ExpectFirstBlockMappingKey();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectFirstBlockMappingKey implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            new ExpectBlockMappingKey(true).expect();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectBlockMappingKey implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        private final boolean first;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        public ExpectBlockMappingKey(boolean first) {
							 | 
						||
| 
								 | 
							
								+            this.first = first;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            event = blockCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            writeBlockComment();
							 | 
						||
| 
								 | 
							
								+            if (!this.first && event instanceof MappingEndEvent) {
							 | 
						||
| 
								 | 
							
								+                indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+                state = states.pop();
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                writeIndent();
							 | 
						||
| 
								 | 
							
								+                if (checkSimpleKey()) {
							 | 
						||
| 
								 | 
							
								+                    states.push(new ExpectBlockMappingSimpleValue());
							 | 
						||
| 
								 | 
							
								+                    expectNode(false, true, true);
							 | 
						||
| 
								 | 
							
								+                } else {
							 | 
						||
| 
								 | 
							
								+                    writeIndicator("?", true, false, true);
							 | 
						||
| 
								 | 
							
								+                    states.push(new ExpectBlockMappingValue());
							 | 
						||
| 
								 | 
							
								+                    expectNode(false, true, false);
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean isFoldedOrLiteral(Event event) {
							 | 
						||
| 
								 | 
							
								+        if(!event.is(ID.Scalar)) {
							 | 
						||
| 
								 | 
							
								+            return false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        ScalarEvent scalarEvent = (ScalarEvent) event;
							 | 
						||
| 
								 | 
							
								+        ScalarStyle style = scalarEvent.getScalarStyle();
							 | 
						||
| 
								 | 
							
								+        return style == ScalarStyle.FOLDED || style == ScalarStyle.LITERAL;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectBlockMappingSimpleValue implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            writeIndicator(":", false, false, false);
							 | 
						||
| 
								 | 
							
								+            event = inlineCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            if(!isFoldedOrLiteral(event)) {
							 | 
						||
| 
								 | 
							
								+                if(writeInlineComments()) {
							 | 
						||
| 
								 | 
							
								+                    increaseIndent(true, false);
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                    indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            event = blockCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            if(!blockCommentsCollector.isEmpty()) {
							 | 
						||
| 
								 | 
							
								+                increaseIndent(true, false);
							 | 
						||
| 
								 | 
							
								+                writeBlockComment();
							 | 
						||
| 
								 | 
							
								+                writeIndent();
							 | 
						||
| 
								 | 
							
								+                indent = indents.pop();
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            states.push(new ExpectBlockMappingKey(false));
							 | 
						||
| 
								 | 
							
								+            expectNode(false, true, false);
							 | 
						||
| 
								 | 
							
								+            inlineCommentsCollector.collectEvents();
							 | 
						||
| 
								 | 
							
								+            writeInlineComments();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private class ExpectBlockMappingValue implements EmitterState {
							 | 
						||
| 
								 | 
							
								+        public void expect() throws IOException {
							 | 
						||
| 
								 | 
							
								+            writeIndent();
							 | 
						||
| 
								 | 
							
								+            writeIndicator(":", true, false, true);
							 | 
						||
| 
								 | 
							
								+            event = inlineCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            writeInlineComments();
							 | 
						||
| 
								 | 
							
								+            event = blockCommentsCollector.collectEventsAndPoll(event);
							 | 
						||
| 
								 | 
							
								+            writeBlockComment();
							 | 
						||
| 
								 | 
							
								+            states.push(new ExpectBlockMappingKey(false));
							 | 
						||
| 
								 | 
							
								+            expectNode(false, true, false);
							 | 
						||
| 
								 | 
							
								+            inlineCommentsCollector.collectEvents(event);
							 | 
						||
| 
								 | 
							
								+            writeInlineComments();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Checkers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean checkEmptySequence() {
							 | 
						||
| 
								 | 
							
								+        return event instanceof SequenceStartEvent && !events.isEmpty() && events.peek() instanceof SequenceEndEvent;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean checkEmptyMapping() {
							 | 
						||
| 
								 | 
							
								+        return event instanceof MappingStartEvent && !events.isEmpty() && events.peek() instanceof MappingEndEvent;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean checkEmptyDocument() {
							 | 
						||
| 
								 | 
							
								+        if (!(event instanceof DocumentStartEvent) || events.isEmpty()) {
							 | 
						||
| 
								 | 
							
								+            return false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        Event event = events.peek();
							 | 
						||
| 
								 | 
							
								+        if (event instanceof ScalarEvent) {
							 | 
						||
| 
								 | 
							
								+            ScalarEvent e = (ScalarEvent) event;
							 | 
						||
| 
								 | 
							
								+            return e.getAnchor() == null && e.getTag() == null && e.getImplicit() != null && e
							 | 
						||
| 
								 | 
							
								+                .getValue().length() == 0;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return false;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean checkSimpleKey() {
							 | 
						||
| 
								 | 
							
								+        int length = 0;
							 | 
						||
| 
								 | 
							
								+        if (event instanceof NodeEvent && ((NodeEvent) event).getAnchor() != null) {
							 | 
						||
| 
								 | 
							
								+            if (preparedAnchor == null) {
							 | 
						||
| 
								 | 
							
								+                preparedAnchor = prepareAnchor(((NodeEvent) event).getAnchor());
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            length += preparedAnchor.length();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        String tag = null;
							 | 
						||
| 
								 | 
							
								+        if (event instanceof ScalarEvent) {
							 | 
						||
| 
								 | 
							
								+            tag = ((ScalarEvent) event).getTag();
							 | 
						||
| 
								 | 
							
								+        } else if (event instanceof CollectionStartEvent) {
							 | 
						||
| 
								 | 
							
								+            tag = ((CollectionStartEvent) event).getTag();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (tag != null) {
							 | 
						||
| 
								 | 
							
								+            if (preparedTag == null) {
							 | 
						||
| 
								 | 
							
								+                preparedTag = prepareTag(tag);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            length += preparedTag.length();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (event instanceof ScalarEvent) {
							 | 
						||
| 
								 | 
							
								+            if (analysis == null) {
							 | 
						||
| 
								 | 
							
								+                analysis = analyzeScalar(((ScalarEvent) event).getValue());
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            length += analysis.getScalar().length();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return length < maxSimpleKeyLength && (event instanceof AliasEvent
							 | 
						||
| 
								 | 
							
								+            || (event instanceof ScalarEvent && !analysis.isEmpty() && !analysis.isMultiline())
							 | 
						||
| 
								 | 
							
								+            || checkEmptySequence() || checkEmptyMapping());
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Anchor, Tag, and Scalar processors.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void processAnchor(String indicator) throws IOException {
							 | 
						||
| 
								 | 
							
								+        NodeEvent ev = (NodeEvent) event;
							 | 
						||
| 
								 | 
							
								+        if (ev.getAnchor() == null) {
							 | 
						||
| 
								 | 
							
								+            preparedAnchor = null;
							 | 
						||
| 
								 | 
							
								+            return;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (preparedAnchor == null) {
							 | 
						||
| 
								 | 
							
								+            preparedAnchor = prepareAnchor(ev.getAnchor());
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        writeIndicator(indicator + preparedAnchor, true, false, false);
							 | 
						||
| 
								 | 
							
								+        preparedAnchor = null;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void processTag() throws IOException {
							 | 
						||
| 
								 | 
							
								+        String tag = null;
							 | 
						||
| 
								 | 
							
								+        if (event instanceof ScalarEvent) {
							 | 
						||
| 
								 | 
							
								+            ScalarEvent ev = (ScalarEvent) event;
							 | 
						||
| 
								 | 
							
								+            tag = ev.getTag();
							 | 
						||
| 
								 | 
							
								+            if (style == null) {
							 | 
						||
| 
								 | 
							
								+                style = chooseScalarStyle();
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if ((!canonical || tag == null) && ((style == null && ev.getImplicit()
							 | 
						||
| 
								 | 
							
								+                .canOmitTagInPlainScalar()) || (style != null && ev.getImplicit()
							 | 
						||
| 
								 | 
							
								+                .canOmitTagInNonPlainScalar()))) {
							 | 
						||
| 
								 | 
							
								+                preparedTag = null;
							 | 
						||
| 
								 | 
							
								+                return;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (ev.getImplicit().canOmitTagInPlainScalar() && tag == null) {
							 | 
						||
| 
								 | 
							
								+                tag = "!";
							 | 
						||
| 
								 | 
							
								+                preparedTag = null;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        } else {
							 | 
						||
| 
								 | 
							
								+            CollectionStartEvent ev = (CollectionStartEvent) event;
							 | 
						||
| 
								 | 
							
								+            tag = ev.getTag();
							 | 
						||
| 
								 | 
							
								+            if ((!canonical || tag == null) && ev.getImplicit()) {
							 | 
						||
| 
								 | 
							
								+                preparedTag = null;
							 | 
						||
| 
								 | 
							
								+                return;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (tag == null) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("tag is not specified");
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (preparedTag == null) {
							 | 
						||
| 
								 | 
							
								+            preparedTag = prepareTag(tag);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        writeIndicator(preparedTag, true, false, false);
							 | 
						||
| 
								 | 
							
								+        preparedTag = null;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private DumperOptions.ScalarStyle chooseScalarStyle() {
							 | 
						||
| 
								 | 
							
								+        ScalarEvent ev = (ScalarEvent) event;
							 | 
						||
| 
								 | 
							
								+        if (analysis == null) {
							 | 
						||
| 
								 | 
							
								+            analysis = analyzeScalar(ev.getValue());
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (!ev.isPlain() && ev.getScalarStyle() == DumperOptions.ScalarStyle.DOUBLE_QUOTED || this.canonical) {
							 | 
						||
| 
								 | 
							
								+            return DumperOptions.ScalarStyle.DOUBLE_QUOTED;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (ev.isPlain() && ev.getImplicit().canOmitTagInPlainScalar()) {
							 | 
						||
| 
								 | 
							
								+            if (!(simpleKeyContext && (analysis.isEmpty() || analysis.isMultiline()))
							 | 
						||
| 
								 | 
							
								+                && ((flowLevel != 0 && analysis.isAllowFlowPlain()) || (flowLevel == 0 && analysis.isAllowBlockPlain()))) {
							 | 
						||
| 
								 | 
							
								+                return null;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (!ev.isPlain() && (ev.getScalarStyle() == DumperOptions.ScalarStyle.LITERAL || ev.getScalarStyle() == DumperOptions.ScalarStyle.FOLDED)) {
							 | 
						||
| 
								 | 
							
								+            if (flowLevel == 0 && !simpleKeyContext && analysis.isAllowBlock()) {
							 | 
						||
| 
								 | 
							
								+                return ev.getScalarStyle();
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (ev.isPlain() || ev.getScalarStyle() == DumperOptions.ScalarStyle.SINGLE_QUOTED) {
							 | 
						||
| 
								 | 
							
								+            if (analysis.isAllowSingleQuoted() && !(simpleKeyContext && analysis.isMultiline())) {
							 | 
						||
| 
								 | 
							
								+                return DumperOptions.ScalarStyle.SINGLE_QUOTED;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return DumperOptions.ScalarStyle.DOUBLE_QUOTED;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void processScalar() throws IOException {
							 | 
						||
| 
								 | 
							
								+        ScalarEvent ev = (ScalarEvent) event;
							 | 
						||
| 
								 | 
							
								+        if (analysis == null) {
							 | 
						||
| 
								 | 
							
								+            analysis = analyzeScalar(ev.getValue());
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (style == null) {
							 | 
						||
| 
								 | 
							
								+            style = chooseScalarStyle();
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        boolean split = !simpleKeyContext && splitLines;
							 | 
						||
| 
								 | 
							
								+        if (style == null) {
							 | 
						||
| 
								 | 
							
								+            writePlain(analysis.getScalar(), split);
							 | 
						||
| 
								 | 
							
								+        } else {
							 | 
						||
| 
								 | 
							
								+            switch (style) {
							 | 
						||
| 
								 | 
							
								+                case DOUBLE_QUOTED:
							 | 
						||
| 
								 | 
							
								+                    writeDoubleQuoted(analysis.getScalar(), split);
							 | 
						||
| 
								 | 
							
								+                    break;
							 | 
						||
| 
								 | 
							
								+                case SINGLE_QUOTED:
							 | 
						||
| 
								 | 
							
								+                    writeSingleQuoted(analysis.getScalar(), split);
							 | 
						||
| 
								 | 
							
								+                    break;
							 | 
						||
| 
								 | 
							
								+                case FOLDED:
							 | 
						||
| 
								 | 
							
								+                    writeFolded(analysis.getScalar(), split);
							 | 
						||
| 
								 | 
							
								+                    break;
							 | 
						||
| 
								 | 
							
								+                case LITERAL:
							 | 
						||
| 
								 | 
							
								+                    writeLiteral(analysis.getScalar());
							 | 
						||
| 
								 | 
							
								+                    break;
							 | 
						||
| 
								 | 
							
								+                default:
							 | 
						||
| 
								 | 
							
								+                    throw new YAMLException("Unexpected style: " + style);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        analysis = null;
							 | 
						||
| 
								 | 
							
								+        style = null;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Analyzers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private String prepareVersion(Version version) {
							 | 
						||
| 
								 | 
							
								+        if (version.major() != 1) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("unsupported YAML version: " + version);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return version.getRepresentation();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private final static Pattern HANDLE_FORMAT = Pattern.compile("^![-_\\w]*!$");
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private String prepareTagHandle(String handle) {
							 | 
						||
| 
								 | 
							
								+        if (handle.length() == 0) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("tag handle must not be empty");
							 | 
						||
| 
								 | 
							
								+        } else if (handle.charAt(0) != '!' || handle.charAt(handle.length() - 1) != '!') {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("tag handle must start and end with '!': " + handle);
							 | 
						||
| 
								 | 
							
								+        } else if (!"!".equals(handle) && !HANDLE_FORMAT.matcher(handle).matches()) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("invalid character in the tag handle: " + handle);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return handle;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private String prepareTagPrefix(String prefix) {
							 | 
						||
| 
								 | 
							
								+        if (prefix.length() == 0) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("tag prefix must not be empty");
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        StringBuilder chunks = new StringBuilder();
							 | 
						||
| 
								 | 
							
								+        int start = 0;
							 | 
						||
| 
								 | 
							
								+        int end = 0;
							 | 
						||
| 
								 | 
							
								+        if (prefix.charAt(0) == '!') {
							 | 
						||
| 
								 | 
							
								+            end = 1;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        while (end < prefix.length()) {
							 | 
						||
| 
								 | 
							
								+            end++;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (start < end) {
							 | 
						||
| 
								 | 
							
								+            chunks.append(prefix, start, end);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return chunks.toString();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private String prepareTag(String tag) {
							 | 
						||
| 
								 | 
							
								+        if (tag.length() == 0) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("tag must not be empty");
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if ("!".equals(tag)) {
							 | 
						||
| 
								 | 
							
								+            return tag;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        String handle = null;
							 | 
						||
| 
								 | 
							
								+        String suffix = tag;
							 | 
						||
| 
								 | 
							
								+        // shall the tag prefixes be sorted as in PyYAML?
							 | 
						||
| 
								 | 
							
								+        for (String prefix : tagPrefixes.keySet()) {
							 | 
						||
| 
								 | 
							
								+            if (tag.startsWith(prefix) && ("!".equals(prefix) || prefix.length() < tag.length())) {
							 | 
						||
| 
								 | 
							
								+                handle = prefix;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (handle != null) {
							 | 
						||
| 
								 | 
							
								+            suffix = tag.substring(handle.length());
							 | 
						||
| 
								 | 
							
								+            handle = tagPrefixes.get(handle);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        int end = suffix.length();
							 | 
						||
| 
								 | 
							
								+        String suffixText = end > 0 ? suffix.substring(0, end) : "";
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        if (handle != null) {
							 | 
						||
| 
								 | 
							
								+            return handle + suffixText;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return "!<" + suffixText + ">";
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    static String prepareAnchor(String anchor) {
							 | 
						||
| 
								 | 
							
								+        if (anchor.length() == 0) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("anchor must not be empty");
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        for (Character invalid : INVALID_ANCHOR) {
							 | 
						||
| 
								 | 
							
								+            if (anchor.indexOf(invalid) > -1) {
							 | 
						||
| 
								 | 
							
								+                throw new EmitterException("Invalid character '" + invalid + "' in the anchor: " + anchor);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        Matcher matcher = SPACES_PATTERN.matcher(anchor);
							 | 
						||
| 
								 | 
							
								+        if (matcher.find()) {
							 | 
						||
| 
								 | 
							
								+            throw new EmitterException("Anchor may not contain spaces: " + anchor);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return anchor;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private ScalarAnalysis analyzeScalar(String scalar) {
							 | 
						||
| 
								 | 
							
								+        // Empty scalar is a special case.
							 | 
						||
| 
								 | 
							
								+        if (scalar.length() == 0) {
							 | 
						||
| 
								 | 
							
								+            return new ScalarAnalysis(scalar, true, false, false, true, true, false);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // Indicators and special characters.
							 | 
						||
| 
								 | 
							
								+        boolean blockIndicators = false;
							 | 
						||
| 
								 | 
							
								+        boolean flowIndicators = false;
							 | 
						||
| 
								 | 
							
								+        boolean lineBreaks = false;
							 | 
						||
| 
								 | 
							
								+        boolean specialCharacters = false;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // Important whitespace combinations.
							 | 
						||
| 
								 | 
							
								+        boolean leadingSpace = false;
							 | 
						||
| 
								 | 
							
								+        boolean leadingBreak = false;
							 | 
						||
| 
								 | 
							
								+        boolean trailingSpace = false;
							 | 
						||
| 
								 | 
							
								+        boolean trailingBreak = false;
							 | 
						||
| 
								 | 
							
								+        boolean breakSpace = false;
							 | 
						||
| 
								 | 
							
								+        boolean spaceBreak = false;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // Check document indicators.
							 | 
						||
| 
								 | 
							
								+        if (scalar.startsWith("---") || scalar.startsWith("...")) {
							 | 
						||
| 
								 | 
							
								+            blockIndicators = true;
							 | 
						||
| 
								 | 
							
								+            flowIndicators = true;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // First character or preceded by a whitespace.
							 | 
						||
| 
								 | 
							
								+        boolean preceededByWhitespace = true;
							 | 
						||
| 
								 | 
							
								+        boolean followedByWhitespace = scalar.length() == 1 || Constant.NULL_BL_T_LINEBR.has(scalar.codePointAt(1));
							 | 
						||
| 
								 | 
							
								+        // The previous character is a space.
							 | 
						||
| 
								 | 
							
								+        boolean previousSpace = false;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        // The previous character is a break.
							 | 
						||
| 
								 | 
							
								+        boolean previousBreak = false;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        int index = 0;
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        while (index < scalar.length()) {
							 | 
						||
| 
								 | 
							
								+            int c = scalar.codePointAt(index);
							 | 
						||
| 
								 | 
							
								+            // Check for indicators.
							 | 
						||
| 
								 | 
							
								+            if (index == 0) {
							 | 
						||
| 
								 | 
							
								+                // Leading indicators are special characters.
							 | 
						||
| 
								 | 
							
								+                if ("#,[]{}&*!|>'\"%@`".indexOf(c) != -1) {
							 | 
						||
| 
								 | 
							
								+                    flowIndicators = true;
							 | 
						||
| 
								 | 
							
								+                    blockIndicators = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (c == '?' || c == ':') {
							 | 
						||
| 
								 | 
							
								+                    flowIndicators = true;
							 | 
						||
| 
								 | 
							
								+                    if (followedByWhitespace) {
							 | 
						||
| 
								 | 
							
								+                        blockIndicators = true;
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (c == '-' && followedByWhitespace) {
							 | 
						||
| 
								 | 
							
								+                    flowIndicators = true;
							 | 
						||
| 
								 | 
							
								+                    blockIndicators = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                // Some indicators cannot appear within a scalar as well.
							 | 
						||
| 
								 | 
							
								+                if (",?[]{}".indexOf(c) != -1) {
							 | 
						||
| 
								 | 
							
								+                    flowIndicators = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (c == ':') {
							 | 
						||
| 
								 | 
							
								+                    flowIndicators = true;
							 | 
						||
| 
								 | 
							
								+                    if (followedByWhitespace) {
							 | 
						||
| 
								 | 
							
								+                        blockIndicators = true;
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (c == '#' && preceededByWhitespace) {
							 | 
						||
| 
								 | 
							
								+                    flowIndicators = true;
							 | 
						||
| 
								 | 
							
								+                    blockIndicators = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            // Check for line breaks, special, and unicode characters.
							 | 
						||
| 
								 | 
							
								+            boolean isLineBreak = Constant.LINEBR.has(c);
							 | 
						||
| 
								 | 
							
								+            if (isLineBreak) {
							 | 
						||
| 
								 | 
							
								+                lineBreaks = true;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (!(c == '\n' || (0x20 <= c && c <= 0x7E))) {
							 | 
						||
| 
								 | 
							
								+                if (c == 0x85 || (c >= 0xA0 && c <= 0xD7FF)
							 | 
						||
| 
								 | 
							
								+                    || (c >= 0xE000 && c <= 0xFFFD)
							 | 
						||
| 
								 | 
							
								+                    || (c >= 0x10000 && c <= 0x10FFFF)) {
							 | 
						||
| 
								 | 
							
								+                    // unicode is used
							 | 
						||
| 
								 | 
							
								+                    if (!this.allowUnicode) {
							 | 
						||
| 
								 | 
							
								+                        specialCharacters = true;
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                } else {
							 | 
						||
| 
								 | 
							
								+                    specialCharacters = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            // Detect important whitespace combinations.
							 | 
						||
| 
								 | 
							
								+            if (c == ' ') {
							 | 
						||
| 
								 | 
							
								+                if (index == 0) {
							 | 
						||
| 
								 | 
							
								+                    leadingSpace = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (index == scalar.length() - 1) {
							 | 
						||
| 
								 | 
							
								+                    trailingSpace = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (previousBreak) {
							 | 
						||
| 
								 | 
							
								+                    breakSpace = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                previousSpace = true;
							 | 
						||
| 
								 | 
							
								+                previousBreak = false;
							 | 
						||
| 
								 | 
							
								+            } else if (isLineBreak) {
							 | 
						||
| 
								 | 
							
								+                if (index == 0) {
							 | 
						||
| 
								 | 
							
								+                    leadingBreak = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (index == scalar.length() - 1) {
							 | 
						||
| 
								 | 
							
								+                    trailingBreak = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (previousSpace) {
							 | 
						||
| 
								 | 
							
								+                    spaceBreak = true;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                previousSpace = false;
							 | 
						||
| 
								 | 
							
								+                previousBreak = true;
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                previousSpace = false;
							 | 
						||
| 
								 | 
							
								+                previousBreak = false;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+            // Prepare for the next character.
							 | 
						||
| 
								 | 
							
								+            index += Character.charCount(c);
							 | 
						||
| 
								 | 
							
								+            preceededByWhitespace = Constant.NULL_BL_T.has(c) || isLineBreak;
							 | 
						||
| 
								 | 
							
								+            followedByWhitespace = true;
							 | 
						||
| 
								 | 
							
								+            if (index + 1 < scalar.length()) {
							 | 
						||
| 
								 | 
							
								+                int nextIndex = index + Character.charCount(scalar.codePointAt(index));
							 | 
						||
| 
								 | 
							
								+                if (nextIndex < scalar.length()) {
							 | 
						||
| 
								 | 
							
								+                    followedByWhitespace = (Constant.NULL_BL_T.has(scalar.codePointAt(nextIndex))) || isLineBreak;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // Let's decide what styles are allowed.
							 | 
						||
| 
								 | 
							
								+        boolean allowFlowPlain = true;
							 | 
						||
| 
								 | 
							
								+        boolean allowBlockPlain = true;
							 | 
						||
| 
								 | 
							
								+        boolean allowSingleQuoted = true;
							 | 
						||
| 
								 | 
							
								+        boolean allowBlock = true;
							 | 
						||
| 
								 | 
							
								+        // Leading and trailing whitespaces are bad for plain scalars.
							 | 
						||
| 
								 | 
							
								+        if (leadingSpace || leadingBreak || trailingSpace || trailingBreak) {
							 | 
						||
| 
								 | 
							
								+            allowFlowPlain = allowBlockPlain = false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // We do not permit trailing spaces for block scalars.
							 | 
						||
| 
								 | 
							
								+        if (trailingSpace) {
							 | 
						||
| 
								 | 
							
								+            allowBlock = false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // Spaces at the beginning of a new line are only acceptable for block
							 | 
						||
| 
								 | 
							
								+        // scalars.
							 | 
						||
| 
								 | 
							
								+        if (breakSpace) {
							 | 
						||
| 
								 | 
							
								+            allowFlowPlain = allowBlockPlain = allowSingleQuoted = false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // Spaces followed by breaks, as well as special character are only
							 | 
						||
| 
								 | 
							
								+        // allowed for double quoted scalars.
							 | 
						||
| 
								 | 
							
								+        if (spaceBreak || specialCharacters) {
							 | 
						||
| 
								 | 
							
								+            allowFlowPlain = allowBlockPlain = allowSingleQuoted = allowBlock = false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // Although the plain scalar writer supports breaks, we never emit
							 | 
						||
| 
								 | 
							
								+        // multiline plain scalars in the flow context.
							 | 
						||
| 
								 | 
							
								+        if (lineBreaks) {
							 | 
						||
| 
								 | 
							
								+            allowFlowPlain = false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // Flow indicators are forbidden for flow plain scalars.
							 | 
						||
| 
								 | 
							
								+        if (flowIndicators) {
							 | 
						||
| 
								 | 
							
								+            allowFlowPlain = false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        // Block indicators are forbidden for block plain scalars.
							 | 
						||
| 
								 | 
							
								+        if (blockIndicators) {
							 | 
						||
| 
								 | 
							
								+            allowBlockPlain = false;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        return new ScalarAnalysis(scalar, false, lineBreaks, allowFlowPlain, allowBlockPlain,
							 | 
						||
| 
								 | 
							
								+            allowSingleQuoted, allowBlock);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Writers.
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void flushStream() throws IOException {
							 | 
						||
| 
								 | 
							
								+        stream.flush();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writeStreamStart() {
							 | 
						||
| 
								 | 
							
								+        // BOM is written by Writer.
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writeStreamEnd() throws IOException {
							 | 
						||
| 
								 | 
							
								+        flushStream();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writeIndicator(String indicator, boolean needWhitespace, boolean whitespace,
							 | 
						||
| 
								 | 
							
								+                        boolean indentation) throws IOException {
							 | 
						||
| 
								 | 
							
								+        if (!this.whitespace && needWhitespace) {
							 | 
						||
| 
								 | 
							
								+            this.column++;
							 | 
						||
| 
								 | 
							
								+            stream.write(SPACE);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        this.whitespace = whitespace;
							 | 
						||
| 
								 | 
							
								+        this.indention = this.indention && indentation;
							 | 
						||
| 
								 | 
							
								+        this.column += indicator.length();
							 | 
						||
| 
								 | 
							
								+        openEnded = false;
							 | 
						||
| 
								 | 
							
								+        stream.write(indicator);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writeIndent() throws IOException {
							 | 
						||
| 
								 | 
							
								+        int indent;
							 | 
						||
| 
								 | 
							
								+        if (this.indent != null) {
							 | 
						||
| 
								 | 
							
								+            indent = this.indent;
							 | 
						||
| 
								 | 
							
								+        } else {
							 | 
						||
| 
								 | 
							
								+            indent = 0;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        if (!this.indention || this.column > indent || (this.column == indent && !this.whitespace)) {
							 | 
						||
| 
								 | 
							
								+            writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+        writeWhitespace(indent - this.column);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void writeWhitespace(int length) throws IOException {
							 | 
						||
| 
								 | 
							
								+        if (length <= 0) {
							 | 
						||
| 
								 | 
							
								+            return;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        this.whitespace = true;
							 | 
						||
| 
								 | 
							
								+        char[] data = new char[length];
							 | 
						||
| 
								 | 
							
								+        for (int i = 0; i < data.length; i++) {
							 | 
						||
| 
								 | 
							
								+            data[i] = ' ';
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        this.column += length;
							 | 
						||
| 
								 | 
							
								+        stream.write(data);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void writeLineBreak(String data) throws IOException {
							 | 
						||
| 
								 | 
							
								+        this.whitespace = true;
							 | 
						||
| 
								 | 
							
								+        this.indention = true;
							 | 
						||
| 
								 | 
							
								+        this.column = 0;
							 | 
						||
| 
								 | 
							
								+        if (data == null) {
							 | 
						||
| 
								 | 
							
								+            stream.write(this.bestLineBreak);
							 | 
						||
| 
								 | 
							
								+        } else {
							 | 
						||
| 
								 | 
							
								+            stream.write(data);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writeVersionDirective(String versionText) throws IOException {
							 | 
						||
| 
								 | 
							
								+        stream.write("%YAML ");
							 | 
						||
| 
								 | 
							
								+        stream.write(versionText);
							 | 
						||
| 
								 | 
							
								+        writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writeTagDirective(String handleText, String prefixText) throws IOException {
							 | 
						||
| 
								 | 
							
								+        // XXX: not sure 4 invocations better then StringBuilders created by str
							 | 
						||
| 
								 | 
							
								+        // + str
							 | 
						||
| 
								 | 
							
								+        stream.write("%TAG ");
							 | 
						||
| 
								 | 
							
								+        stream.write(handleText);
							 | 
						||
| 
								 | 
							
								+        stream.write(SPACE);
							 | 
						||
| 
								 | 
							
								+        stream.write(prefixText);
							 | 
						||
| 
								 | 
							
								+        writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    // Scalar streams.
							 | 
						||
| 
								 | 
							
								+    private void writeSingleQuoted(String text, boolean split) throws IOException {
							 | 
						||
| 
								 | 
							
								+        writeIndicator("'", true, false, false);
							 | 
						||
| 
								 | 
							
								+        boolean spaces = false;
							 | 
						||
| 
								 | 
							
								+        boolean breaks = false;
							 | 
						||
| 
								 | 
							
								+        int start = 0, end = 0;
							 | 
						||
| 
								 | 
							
								+        char ch;
							 | 
						||
| 
								 | 
							
								+        while (end <= text.length()) {
							 | 
						||
| 
								 | 
							
								+            ch = 0;
							 | 
						||
| 
								 | 
							
								+            if (end < text.length()) {
							 | 
						||
| 
								 | 
							
								+                ch = text.charAt(end);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (spaces) {
							 | 
						||
| 
								 | 
							
								+                if (ch == 0 || ch != ' ') {
							 | 
						||
| 
								 | 
							
								+                    if (start + 1 == end && this.column > this.bestWidth && split && start != 0
							 | 
						||
| 
								 | 
							
								+                        && end != text.length()) {
							 | 
						||
| 
								 | 
							
								+                        writeIndent();
							 | 
						||
| 
								 | 
							
								+                    } else {
							 | 
						||
| 
								 | 
							
								+                        int len = end - start;
							 | 
						||
| 
								 | 
							
								+                        this.column += len;
							 | 
						||
| 
								 | 
							
								+                        stream.write(text, start, len);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else if (breaks) {
							 | 
						||
| 
								 | 
							
								+                if (ch == 0 || Constant.LINEBR.hasNo(ch)) {
							 | 
						||
| 
								 | 
							
								+                    if (text.charAt(start) == '\n') {
							 | 
						||
| 
								 | 
							
								+                        writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    String data = text.substring(start, end);
							 | 
						||
| 
								 | 
							
								+                    for (char br : data.toCharArray()) {
							 | 
						||
| 
								 | 
							
								+                        if (br == '\n') {
							 | 
						||
| 
								 | 
							
								+                            writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                        } else {
							 | 
						||
| 
								 | 
							
								+                            writeLineBreak(String.valueOf(br));
							 | 
						||
| 
								 | 
							
								+                        }
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                if (Constant.LINEBR.has(ch, "\0 '")) {
							 | 
						||
| 
								 | 
							
								+                    if (start < end) {
							 | 
						||
| 
								 | 
							
								+                        int len = end - start;
							 | 
						||
| 
								 | 
							
								+                        this.column += len;
							 | 
						||
| 
								 | 
							
								+                        stream.write(text, start, len);
							 | 
						||
| 
								 | 
							
								+                        start = end;
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (ch == '\'') {
							 | 
						||
| 
								 | 
							
								+                this.column += 2;
							 | 
						||
| 
								 | 
							
								+                stream.write("''");
							 | 
						||
| 
								 | 
							
								+                start = end + 1;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (ch != 0) {
							 | 
						||
| 
								 | 
							
								+                spaces = ch == ' ';
							 | 
						||
| 
								 | 
							
								+                breaks = Constant.LINEBR.has(ch);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            end++;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        writeIndicator("'", false, false, false);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void writeDoubleQuoted(String text, boolean split) throws IOException {
							 | 
						||
| 
								 | 
							
								+        writeIndicator("\"", true, false, false);
							 | 
						||
| 
								 | 
							
								+        int start = 0;
							 | 
						||
| 
								 | 
							
								+        int end = 0;
							 | 
						||
| 
								 | 
							
								+        while (end <= text.length()) {
							 | 
						||
| 
								 | 
							
								+            Character ch = null;
							 | 
						||
| 
								 | 
							
								+            if (end < text.length()) {
							 | 
						||
| 
								 | 
							
								+                ch = text.charAt(end);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (ch == null || "\"\\\u0085\u2028\u2029\uFEFF".indexOf(ch) != -1
							 | 
						||
| 
								 | 
							
								+                || !('\u0020' <= ch && ch <= '\u007E')) {
							 | 
						||
| 
								 | 
							
								+                if (start < end) {
							 | 
						||
| 
								 | 
							
								+                    int len = end - start;
							 | 
						||
| 
								 | 
							
								+                    this.column += len;
							 | 
						||
| 
								 | 
							
								+                    stream.write(text, start, len);
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (ch != null) {
							 | 
						||
| 
								 | 
							
								+                    String data;
							 | 
						||
| 
								 | 
							
								+                    if (ESCAPE_REPLACEMENTS.containsKey(ch)) {
							 | 
						||
| 
								 | 
							
								+                        data = "\\" + ESCAPE_REPLACEMENTS.get(ch);
							 | 
						||
| 
								 | 
							
								+                    } else if (!this.allowUnicode || !StreamReader.isPrintable(ch)) {
							 | 
						||
| 
								 | 
							
								+                        // if !allowUnicode or the character is not printable,
							 | 
						||
| 
								 | 
							
								+                        // we must encode it
							 | 
						||
| 
								 | 
							
								+                        if (ch <= '\u00FF') {
							 | 
						||
| 
								 | 
							
								+                            String s = "0" + Integer.toString(ch, 16);
							 | 
						||
| 
								 | 
							
								+                            data = "\\x" + s.substring(s.length() - 2);
							 | 
						||
| 
								 | 
							
								+                        } else if (ch >= '\uD800' && ch <= '\uDBFF') {
							 | 
						||
| 
								 | 
							
								+                            if (end + 1 < text.length()) {
							 | 
						||
| 
								 | 
							
								+                                Character ch2 = text.charAt(++end);
							 | 
						||
| 
								 | 
							
								+                                String s = "000" + Long.toHexString(Character.toCodePoint(ch, ch2));
							 | 
						||
| 
								 | 
							
								+                                data = "\\U" + s.substring(s.length() - 8);
							 | 
						||
| 
								 | 
							
								+                            } else {
							 | 
						||
| 
								 | 
							
								+                                String s = "000" + Integer.toString(ch, 16);
							 | 
						||
| 
								 | 
							
								+                                data = "\\u" + s.substring(s.length() - 4);
							 | 
						||
| 
								 | 
							
								+                            }
							 | 
						||
| 
								 | 
							
								+                        } else {
							 | 
						||
| 
								 | 
							
								+                            String s = "000" + Integer.toString(ch, 16);
							 | 
						||
| 
								 | 
							
								+                            data = "\\u" + s.substring(s.length() - 4);
							 | 
						||
| 
								 | 
							
								+                        }
							 | 
						||
| 
								 | 
							
								+                    } else {
							 | 
						||
| 
								 | 
							
								+                        data = String.valueOf(ch);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    this.column += data.length();
							 | 
						||
| 
								 | 
							
								+                    stream.write(data);
							 | 
						||
| 
								 | 
							
								+                    start = end + 1;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if ((0 < end && end < (text.length() - 1)) && (ch == ' ' || start >= end)
							 | 
						||
| 
								 | 
							
								+                && (this.column + (end - start)) > this.bestWidth && split) {
							 | 
						||
| 
								 | 
							
								+                String data;
							 | 
						||
| 
								 | 
							
								+                if (start >= end) {
							 | 
						||
| 
								 | 
							
								+                    data = "\\";
							 | 
						||
| 
								 | 
							
								+                } else {
							 | 
						||
| 
								 | 
							
								+                    data = text.substring(start, end) + "\\";
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                if (start < end) {
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                this.column += data.length();
							 | 
						||
| 
								 | 
							
								+                stream.write(data);
							 | 
						||
| 
								 | 
							
								+                writeIndent();
							 | 
						||
| 
								 | 
							
								+                this.whitespace = false;
							 | 
						||
| 
								 | 
							
								+                this.indention = false;
							 | 
						||
| 
								 | 
							
								+                if (text.charAt(start) == ' ') {
							 | 
						||
| 
								 | 
							
								+                    data = "\\";
							 | 
						||
| 
								 | 
							
								+                    this.column += data.length();
							 | 
						||
| 
								 | 
							
								+                    stream.write(data);
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            end += 1;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        writeIndicator("\"", false, false, false);
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean writeCommentLines(List<CommentLine> commentLines) throws IOException {
							 | 
						||
| 
								 | 
							
								+        boolean wroteComment = false;
							 | 
						||
| 
								 | 
							
								+        if(emitComments) {
							 | 
						||
| 
								 | 
							
								+            int indentColumns = 0;
							 | 
						||
| 
								 | 
							
								+            boolean firstComment = true;
							 | 
						||
| 
								 | 
							
								+            for (CommentLine commentLine : commentLines) {
							 | 
						||
| 
								 | 
							
								+                if (commentLine.getCommentType() != CommentType.BLANK_LINE) {
							 | 
						||
| 
								 | 
							
								+                    if (firstComment) {
							 | 
						||
| 
								 | 
							
								+                        firstComment = false;
							 | 
						||
| 
								 | 
							
								+                        writeIndicator("#", commentLine.getCommentType() == CommentType.IN_LINE, false, false);
							 | 
						||
| 
								 | 
							
								+                        indentColumns = this.column > 0 ? this.column - 1 : 0;
							 | 
						||
| 
								 | 
							
								+                    } else {
							 | 
						||
| 
								 | 
							
								+                        writeWhitespace(indentColumns);
							 | 
						||
| 
								 | 
							
								+                        writeIndicator("#", false, false, false);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    stream.write(commentLine.getValue());
							 | 
						||
| 
								 | 
							
								+                    writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                } else {
							 | 
						||
| 
								 | 
							
								+                    writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+                wroteComment = true;
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return wroteComment;
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private void writeBlockComment() throws IOException {
							 | 
						||
| 
								 | 
							
								+        if(!blockCommentsCollector.isEmpty()) {
							 | 
						||
| 
								 | 
							
								+            writeIndent();
							 | 
						||
| 
								 | 
							
								+            writeCommentLines(blockCommentsCollector.consume());
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private boolean writeInlineComments() throws IOException {
							 | 
						||
| 
								 | 
							
								+        return writeCommentLines(inlineCommentsCollector.consume());
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    private String determineBlockHints(String text) {
							 | 
						||
| 
								 | 
							
								+        StringBuilder hints = new StringBuilder();
							 | 
						||
| 
								 | 
							
								+        if (Constant.LINEBR.has(text.charAt(0), " ")) {
							 | 
						||
| 
								 | 
							
								+            hints.append(bestIndent);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        char ch1 = text.charAt(text.length() - 1);
							 | 
						||
| 
								 | 
							
								+        if (Constant.LINEBR.hasNo(ch1)) {
							 | 
						||
| 
								 | 
							
								+            hints.append("-");
							 | 
						||
| 
								 | 
							
								+        } else if (text.length() == 1 || Constant.LINEBR.has(text.charAt(text.length() - 2))) {
							 | 
						||
| 
								 | 
							
								+            hints.append("+");
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        return hints.toString();
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writeFolded(String text, boolean split) throws IOException {
							 | 
						||
| 
								 | 
							
								+        String hints = determineBlockHints(text);
							 | 
						||
| 
								 | 
							
								+        writeIndicator(">" + hints, true, false, false);
							 | 
						||
| 
								 | 
							
								+        if (hints.length() > 0 && (hints.charAt(hints.length() - 1) == '+')) {
							 | 
						||
| 
								 | 
							
								+            openEnded = true;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if(!writeInlineComments()) {
							 | 
						||
| 
								 | 
							
								+            writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        boolean leadingSpace = true;
							 | 
						||
| 
								 | 
							
								+        boolean spaces = false;
							 | 
						||
| 
								 | 
							
								+        boolean breaks = true;
							 | 
						||
| 
								 | 
							
								+        int start = 0, end = 0;
							 | 
						||
| 
								 | 
							
								+        while (end <= text.length()) {
							 | 
						||
| 
								 | 
							
								+            char ch = 0;
							 | 
						||
| 
								 | 
							
								+            if (end < text.length()) {
							 | 
						||
| 
								 | 
							
								+                ch = text.charAt(end);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (breaks) {
							 | 
						||
| 
								 | 
							
								+                if (ch == 0 || Constant.LINEBR.hasNo(ch)) {
							 | 
						||
| 
								 | 
							
								+                    if (!leadingSpace && ch != 0 && ch != ' ' && text.charAt(start) == '\n') {
							 | 
						||
| 
								 | 
							
								+                        writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    leadingSpace = ch == ' ';
							 | 
						||
| 
								 | 
							
								+                    String data = text.substring(start, end);
							 | 
						||
| 
								 | 
							
								+                    for (char br : data.toCharArray()) {
							 | 
						||
| 
								 | 
							
								+                        if (br == '\n') {
							 | 
						||
| 
								 | 
							
								+                            writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                        } else {
							 | 
						||
| 
								 | 
							
								+                            writeLineBreak(String.valueOf(br));
							 | 
						||
| 
								 | 
							
								+                        }
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    if (ch != 0) {
							 | 
						||
| 
								 | 
							
								+                        writeIndent();
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else if (spaces) {
							 | 
						||
| 
								 | 
							
								+                if (ch != ' ') {
							 | 
						||
| 
								 | 
							
								+                    if (start + 1 == end && this.column > this.bestWidth && split) {
							 | 
						||
| 
								 | 
							
								+                        writeIndent();
							 | 
						||
| 
								 | 
							
								+                    } else {
							 | 
						||
| 
								 | 
							
								+                        int len = end - start;
							 | 
						||
| 
								 | 
							
								+                        this.column += len;
							 | 
						||
| 
								 | 
							
								+                        stream.write(text, start, len);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                if (Constant.LINEBR.has(ch, "\0 ")) {
							 | 
						||
| 
								 | 
							
								+                    int len = end - start;
							 | 
						||
| 
								 | 
							
								+                    this.column += len;
							 | 
						||
| 
								 | 
							
								+                    stream.write(text, start, len);
							 | 
						||
| 
								 | 
							
								+                    if (ch == 0) {
							 | 
						||
| 
								 | 
							
								+                        writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (ch != 0) {
							 | 
						||
| 
								 | 
							
								+                breaks = Constant.LINEBR.has(ch);
							 | 
						||
| 
								 | 
							
								+                spaces = ch == ' ';
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            end++;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writeLiteral(String text) throws IOException {
							 | 
						||
| 
								 | 
							
								+        String hints = determineBlockHints(text);
							 | 
						||
| 
								 | 
							
								+        writeIndicator("|" + hints, true, false, false);
							 | 
						||
| 
								 | 
							
								+        if (hints.length() > 0 && (hints.charAt(hints.length() - 1)) == '+') {
							 | 
						||
| 
								 | 
							
								+            openEnded = true;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if(!writeInlineComments()) {
							 | 
						||
| 
								 | 
							
								+            writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        boolean breaks = true;
							 | 
						||
| 
								 | 
							
								+        int start = 0, end = 0;
							 | 
						||
| 
								 | 
							
								+        while (end <= text.length()) {
							 | 
						||
| 
								 | 
							
								+            char ch = 0;
							 | 
						||
| 
								 | 
							
								+            if (end < text.length()) {
							 | 
						||
| 
								 | 
							
								+                ch = text.charAt(end);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (breaks) {
							 | 
						||
| 
								 | 
							
								+                if (ch == 0 || Constant.LINEBR.hasNo(ch)) {
							 | 
						||
| 
								 | 
							
								+                    String data = text.substring(start, end);
							 | 
						||
| 
								 | 
							
								+                    for (char br : data.toCharArray()) {
							 | 
						||
| 
								 | 
							
								+                        if (br == '\n') {
							 | 
						||
| 
								 | 
							
								+                            writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                        } else {
							 | 
						||
| 
								 | 
							
								+                            writeLineBreak(String.valueOf(br));
							 | 
						||
| 
								 | 
							
								+                        }
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    if (ch != 0) {
							 | 
						||
| 
								 | 
							
								+                        writeIndent();
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                if (ch == 0 || Constant.LINEBR.has(ch)) {
							 | 
						||
| 
								 | 
							
								+                    stream.write(text, start, end - start);
							 | 
						||
| 
								 | 
							
								+                    if (ch == 0) {
							 | 
						||
| 
								 | 
							
								+                        writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (ch != 0) {
							 | 
						||
| 
								 | 
							
								+                breaks = Constant.LINEBR.has(ch);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            end++;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+
							 | 
						||
| 
								 | 
							
								+    void writePlain(String text, boolean split) throws IOException {
							 | 
						||
| 
								 | 
							
								+        if (rootContext) {
							 | 
						||
| 
								 | 
							
								+            openEnded = true;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (text.length() == 0) {
							 | 
						||
| 
								 | 
							
								+            return;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        if (!this.whitespace) {
							 | 
						||
| 
								 | 
							
								+            this.column++;
							 | 
						||
| 
								 | 
							
								+            stream.write(SPACE);
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+        this.whitespace = false;
							 | 
						||
| 
								 | 
							
								+        this.indention = false;
							 | 
						||
| 
								 | 
							
								+        boolean spaces = false;
							 | 
						||
| 
								 | 
							
								+        boolean breaks = false;
							 | 
						||
| 
								 | 
							
								+        int start = 0, end = 0;
							 | 
						||
| 
								 | 
							
								+        while (end <= text.length()) {
							 | 
						||
| 
								 | 
							
								+            char ch = 0;
							 | 
						||
| 
								 | 
							
								+            if (end < text.length()) {
							 | 
						||
| 
								 | 
							
								+                ch = text.charAt(end);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (spaces) {
							 | 
						||
| 
								 | 
							
								+                if (ch != ' ') {
							 | 
						||
| 
								 | 
							
								+                    if (start + 1 == end && this.column > this.bestWidth && split) {
							 | 
						||
| 
								 | 
							
								+                        writeIndent();
							 | 
						||
| 
								 | 
							
								+                        this.whitespace = false;
							 | 
						||
| 
								 | 
							
								+                        this.indention = false;
							 | 
						||
| 
								 | 
							
								+                    } else {
							 | 
						||
| 
								 | 
							
								+                        int len = end - start;
							 | 
						||
| 
								 | 
							
								+                        this.column += len;
							 | 
						||
| 
								 | 
							
								+                        stream.write(text, start, len);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else if (breaks) {
							 | 
						||
| 
								 | 
							
								+                if (Constant.LINEBR.hasNo(ch)) {
							 | 
						||
| 
								 | 
							
								+                    if (text.charAt(start) == '\n') {
							 | 
						||
| 
								 | 
							
								+                        writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    String data = text.substring(start, end);
							 | 
						||
| 
								 | 
							
								+                    for (char br : data.toCharArray()) {
							 | 
						||
| 
								 | 
							
								+                        if (br == '\n') {
							 | 
						||
| 
								 | 
							
								+                            writeLineBreak(null);
							 | 
						||
| 
								 | 
							
								+                        } else {
							 | 
						||
| 
								 | 
							
								+                            writeLineBreak(String.valueOf(br));
							 | 
						||
| 
								 | 
							
								+                        }
							 | 
						||
| 
								 | 
							
								+                    }
							 | 
						||
| 
								 | 
							
								+                    writeIndent();
							 | 
						||
| 
								 | 
							
								+                    this.whitespace = false;
							 | 
						||
| 
								 | 
							
								+                    this.indention = false;
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            } else {
							 | 
						||
| 
								 | 
							
								+                if (Constant.LINEBR.has(ch, "\0 ")) {
							 | 
						||
| 
								 | 
							
								+                    int len = end - start;
							 | 
						||
| 
								 | 
							
								+                    this.column += len;
							 | 
						||
| 
								 | 
							
								+                    stream.write(text, start, len);
							 | 
						||
| 
								 | 
							
								+                    start = end;
							 | 
						||
| 
								 | 
							
								+                }
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            if (ch != 0) {
							 | 
						||
| 
								 | 
							
								+                spaces = ch == ' ';
							 | 
						||
| 
								 | 
							
								+                breaks = Constant.LINEBR.has(ch);
							 | 
						||
| 
								 | 
							
								+            }
							 | 
						||
| 
								 | 
							
								+            end++;
							 | 
						||
| 
								 | 
							
								+        }
							 | 
						||
| 
								 | 
							
								+    }
							 | 
						||
| 
								 | 
							
								+}
							 |