1 /**
2  * Copyright (c) 2008, http://www.snakeyaml.org
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.yaml.snakeyaml;
17
18 import java.util.Map;
19 import java.util.TimeZone;
20
21 import org.yaml.snakeyaml.emitter.Emitter;
22 import org.yaml.snakeyaml.error.YAMLException;
23 import org.yaml.snakeyaml.serializer.AnchorGenerator;
24 import org.yaml.snakeyaml.serializer.NumberAnchorGenerator;
25
26 public class DumperOptions {
27     /**
28      * YAML provides a rich set of scalar styles. Block scalar styles include
29      * the literal style and the folded style; flow scalar styles include the
30      * plain style and two quoted styles, the single-quoted style and the
31      * double-quoted style. These styles offer a range of trade-offs between
32      * expressive power and readability.
33      *
34      * @see <a href="http://yaml.org/spec/1.1/#id903915">Chapter 9. Scalar
35      *      Styles</a>
36      * @see <a href="http://yaml.org/spec/1.1/#id858081">2.3. Scalars</a>
37      */

38     public enum ScalarStyle {
39         DOUBLE_QUOTED('"'), SINGLE_QUOTED('\''), LITERAL(
40                 '|'), FOLDED('>'), PLAIN(null);
41         private Character styleChar;
42
43         private ScalarStyle(Character style) {
44             this.styleChar = style;
45         }
46
47         public Character getChar() {
48             return styleChar;
49         }
50
51         @Override
52         public String toString() {
53             return "Scalar style: '" + styleChar + "'";
54         }
55
56         public static ScalarStyle createStyle(Character style) {
57             if (style == null) {
58                 return PLAIN;
59             } else {
60                 switch (style) {
61                 case '"':
62                     return DOUBLE_QUOTED;
63                 case '\'':
64                     return SINGLE_QUOTED;
65                 case '|':
66                     return LITERAL;
67                 case '>':
68                     return FOLDED;
69                 default:
70                     throw new YAMLException("Unknown scalar style character: " + style);
71                 }
72             }
73         }
74     }
75
76     /**
77      * Block styles use indentation to denote nesting and scope within the
78      * document. In contrast, flow styles rely on explicit indicators to denote
79      * nesting and scope.
80      *
81      * @see <a href="http://www.yaml.org/spec/current.html#id2509255">3.2.3.1.
82      *      Node Styles (http://yaml.org/spec/1.1)</a>
83      */

84     public enum FlowStyle {
85         FLOW(Boolean.TRUE), BLOCK(Boolean.FALSE), AUTO(null);
86
87         private Boolean styleBoolean;
88
89         private FlowStyle(Boolean flowStyle) {
90             styleBoolean = flowStyle;
91         }
92         
93         /*
94          * Convenience for legacy constructors that took {@link Boolean} arguments since replaced by {@link FlowStyle}.
95          * Introduced in v1.22 but only to support that for backwards compatibility.
96          * @deprecated Since restored in v1.22.  Use the {@link FlowStyle} constants in your code instead.
97          */

98         @Deprecated
99         public static FlowStyle fromBoolean(Boolean flowStyle) {
100             return flowStyle==null ? AUTO
101                 : flowStyle ? FLOW
102                     : BLOCK;
103         }
104
105         public Boolean getStyleBoolean() {
106             return styleBoolean;
107         }
108
109         @Override
110         public String toString() {
111             return "Flow style: '" + styleBoolean + "'";
112         }
113     }
114
115     /**
116      * Platform dependent line break.
117      */

118     public enum LineBreak {
119         WIN("\r\n"), MAC("\r"), UNIX("\n");
120
121         private String lineBreak;
122
123         private LineBreak(String lineBreak) {
124             this.lineBreak = lineBreak;
125         }
126
127         public String getString() {
128             return lineBreak;
129         }
130
131         @Override
132         public String toString() {
133             return "Line break: " + name();
134         }
135
136         public static LineBreak getPlatformLineBreak() {
137             String platformLineBreak = System.getProperty("line.separator");
138             for (LineBreak lb : values()) {
139                 if (lb.lineBreak.equals(platformLineBreak)) {
140                     return lb;
141                 }
142             }
143             return LineBreak.UNIX;
144         }
145     }
146
147     /**
148      * Specification version. Currently supported 1.0 and 1.1
149      */

150     public enum Version {
151         V1_0(new Integer[] { 1, 0 }), V1_1(new Integer[] { 1, 1 });
152
153         private Integer[] version;
154
155         private Version(Integer[] version) {
156             this.version = version;
157         }
158
159         public int major() { return version[0]; }
160         public int minor() { return version[1]; }
161
162         public String getRepresentation() {
163             return version[0] + "." + version[1];
164         }
165
166         @Override
167         public String toString() {
168             return "Version: " + getRepresentation();
169         }
170     }
171
172     public enum NonPrintableStyle {
173         /**
174          * Tranform String to binary if it contains non-printable characters
175          */

176         BINARY,
177         /**
178          * Escape non-printable characters
179          */

180         ESCAPE
181     }
182
183     private ScalarStyle defaultStyle = ScalarStyle.PLAIN;
184     private FlowStyle defaultFlowStyle = FlowStyle.AUTO;
185     private boolean canonical = false;
186     private boolean allowUnicode = true;
187     private boolean allowReadOnlyProperties = false;
188     private int indent = 2;
189     private int indicatorIndent = 0;
190     private int bestWidth = 80;
191     private boolean splitLines = true;
192     private LineBreak lineBreak = LineBreak.UNIX;
193     private boolean explicitStart = false;
194     private boolean explicitEnd = false;
195     private TimeZone timeZone = null;
196     private int maxSimpleKeyLength = 128;
197     private NonPrintableStyle  nonPrintableStyle = NonPrintableStyle.BINARY;
198
199     private Version version = null;
200     private Map<String, String> tags = null;
201     private Boolean prettyFlow = false;
202     private AnchorGenerator anchorGenerator = new NumberAnchorGenerator(0);
203
204     public boolean isAllowUnicode() {
205         return allowUnicode;
206     }
207
208     /**
209      * Specify whether to emit non-ASCII printable Unicode characters.
210      * The default value is true.
211      * When set to false then printable non-ASCII characters (Cyrillic, Chinese etc)
212      * will be not printed but escaped (to support ASCII terminals)
213      *
214      * @param allowUnicode
215      *            if allowUnicode is false then all non-ASCII characters are
216      *            escaped
217      */

218     public void setAllowUnicode(boolean allowUnicode) {
219         this.allowUnicode = allowUnicode;
220     }
221
222     public ScalarStyle getDefaultScalarStyle() {
223         return defaultStyle;
224     }
225
226     /**
227      * Set default style for scalars. See YAML 1.1 specification, 2.3 Scalars
228      * (http://yaml.org/spec/1.1/#id858081)
229      *
230      * @param defaultStyle
231      *            set the style for all scalars
232      */

233     public void setDefaultScalarStyle(ScalarStyle defaultStyle) {
234         if (defaultStyle == null) {
235             throw new NullPointerException("Use ScalarStyle enum.");
236         }
237         this.defaultStyle = defaultStyle;
238     }
239
240     public void setIndent(int indent) {
241         if (indent < Emitter.MIN_INDENT) {
242             throw new YAMLException("Indent must be at least " + Emitter.MIN_INDENT);
243         }
244         if (indent > Emitter.MAX_INDENT) {
245             throw new YAMLException("Indent must be at most " + Emitter.MAX_INDENT);
246         }
247         this.indent = indent;
248     }
249
250     public int getIndent() {
251         return this.indent;
252     }
253
254     public void setIndicatorIndent(int indicatorIndent) {
255         if (indicatorIndent < 0) {
256             throw new YAMLException("Indicator indent must be non-negative.");
257         }
258         if (indicatorIndent > Emitter.MAX_INDENT - 1) {
259             throw new YAMLException("Indicator indent must be at most Emitter.MAX_INDENT-1: " + (Emitter.MAX_INDENT - 1));
260         }
261         this.indicatorIndent = indicatorIndent;
262     }
263
264     public int getIndicatorIndent() {
265         return this.indicatorIndent;
266     }
267
268     public void setVersion(Version version) {
269         this.version = version;
270     }
271
272     public Version getVersion() {
273         return this.version;
274     }
275
276     /**
277      * Force the emitter to produce a canonical YAML document.
278      *
279      * @param canonical
280      *            true produce canonical YAML document
281      */

282     public void setCanonical(boolean canonical) {
283         this.canonical = canonical;
284     }
285
286     public boolean isCanonical() {
287         return this.canonical;
288     }
289
290     /**
291      * Force the emitter to produce a pretty YAML document when using the flow
292      * style.
293      *
294      * @param prettyFlow
295      *            true produce pretty flow YAML document
296      */

297     public void setPrettyFlow(boolean prettyFlow) {
298         this.prettyFlow = prettyFlow;
299     }
300
301     public boolean isPrettyFlow() {
302         return this.prettyFlow;
303     }
304
305     /**
306      * Specify the preferred width to emit scalars. When the scalar
307      * representation takes more then the preferred with the scalar will be
308      * split into a few lines. The default is 80.
309      *
310      * @param bestWidth
311      *            the preferred width for scalars.
312      */

313     public void setWidth(int bestWidth) {
314         this.bestWidth = bestWidth;
315     }
316
317     public int getWidth() {
318         return this.bestWidth;
319     }
320
321     /**
322      * Specify whether to split lines exceeding preferred width for
323      * scalars. The default is true.
324      *
325      * @param splitLines
326      *            whether to split lines exceeding preferred width for scalars.
327      */

328     public void setSplitLines(boolean splitLines) {
329         this.splitLines = splitLines;
330     }
331
332     public boolean getSplitLines() {
333         return this.splitLines;
334     }
335
336     public LineBreak getLineBreak() {
337         return lineBreak;
338     }
339
340     public void setDefaultFlowStyle(FlowStyle defaultFlowStyle) {
341         if (defaultFlowStyle == null) {
342             throw new NullPointerException("Use FlowStyle enum.");
343         }
344         this.defaultFlowStyle = defaultFlowStyle;
345     }
346
347     public FlowStyle getDefaultFlowStyle() {
348         return defaultFlowStyle;
349     }
350
351     /**
352      * Specify the line break to separate the lines. It is platform specific:
353      * Windows - "\r\n", old MacOS - "\r", Unix - "\n". The default value is the
354      * one for Unix.
355      * @param lineBreak to be used for the input
356      */

357     public void setLineBreak(LineBreak lineBreak) {
358         if (lineBreak == null) {
359             throw new NullPointerException("Specify line break.");
360         }
361         this.lineBreak = lineBreak;
362     }
363
364     public boolean isExplicitStart() {
365         return explicitStart;
366     }
367
368     public void setExplicitStart(boolean explicitStart) {
369         this.explicitStart = explicitStart;
370     }
371
372     public boolean isExplicitEnd() {
373         return explicitEnd;
374     }
375
376     public void setExplicitEnd(boolean explicitEnd) {
377         this.explicitEnd = explicitEnd;
378     }
379
380     public Map<String, String> getTags() {
381         return tags;
382     }
383
384     public void setTags(Map<String, String> tags) {
385         this.tags = tags;
386     }
387
388     /**
389      * Report whether read-only JavaBean properties (the ones without setters)
390      * should be included in the YAML document
391      *
392      * @return false when read-only JavaBean properties are not emitted
393      */

394     public boolean isAllowReadOnlyProperties() {
395         return allowReadOnlyProperties;
396     }
397
398     /**
399      * Set to true to include read-only JavaBean properties (the ones without
400      * setters) in the YAML document. By default these properties are not
401      * included to be able to parse later the same JavaBean.
402      *
403      * @param allowReadOnlyProperties
404      *            - true to dump read-only JavaBean properties
405      */

406     public void setAllowReadOnlyProperties(boolean allowReadOnlyProperties) {
407         this.allowReadOnlyProperties = allowReadOnlyProperties;
408     }
409
410     public TimeZone getTimeZone() {
411         return timeZone;
412     }
413
414     /**
415      * Set the timezone to be used for Date. If set to <code>null</code> UTC is
416      * used.
417      * @param timeZone for created Dates or null to use UTC
418      */

419     public void setTimeZone(TimeZone timeZone) {
420         this.timeZone = timeZone;
421     }
422
423
424     public AnchorGenerator getAnchorGenerator() {
425         return anchorGenerator;
426     }
427
428     public void setAnchorGenerator(AnchorGenerator anchorGenerator) {
429         this.anchorGenerator = anchorGenerator;
430     }
431
432     public int getMaxSimpleKeyLength() {
433         return maxSimpleKeyLength;
434     }
435
436     /**
437      * Define max key length to use simple key (without '?')
438      * More info https://yaml.org/spec/1.1/#id934537
439      * @param maxSimpleKeyLength - the limit after which the key gets explicit key indicator '?'
440      */

441     public void setMaxSimpleKeyLength(int maxSimpleKeyLength) {
442         if(maxSimpleKeyLength > 1024) {
443             throw new YAMLException("The simple key must not span more than 1024 stream characters. See https://yaml.org/spec/1.1/#id934537");
444         }
445         this.maxSimpleKeyLength = maxSimpleKeyLength;
446     }
447
448     public NonPrintableStyle getNonPrintableStyle() {
449         return this.nonPrintableStyle;
450     }
451
452     /**
453      * When String contains non-printable characters SnakeYAML convert it to binary data with the !!binary tag.
454      * Set this to ESCAPE to keep the !!str tag and escape the non-printable chars with \\x or \\u
455      * @param style ESCAPE to force SnakeYAML to keep !!str tag for non-printable data
456      */

457     public void setNonPrintableStyle(NonPrintableStyle style) {
458         this.nonPrintableStyle = style;
459     }
460 }
461