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 */
16package org.yaml.snakeyaml;
17
18import java.util.Map;
19import java.util.TimeZone;
20
21import org.yaml.snakeyaml.emitter.Emitter;
22import org.yaml.snakeyaml.error.YAMLException;
23import org.yaml.snakeyaml.serializer.AnchorGenerator;
24import org.yaml.snakeyaml.serializer.NumberAnchorGenerator;
25
26public 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(Character.valueOf('"')), SINGLE_QUOTED(Character.valueOf('\'')), LITERAL(
40                Character.valueOf('|')), FOLDED(Character.valueOf('>')), 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        public Boolean getStyleBoolean() {
94            return styleBoolean;
95        }
96
97        @Override
98        public String toString() {
99            return "Flow style: '" + styleBoolean + "'";
100        }
101    }
102
103    /**
104     * Platform dependent line break.
105     */
106    public enum LineBreak {
107        WIN("\r\n"), MAC("\r"), UNIX("\n");
108
109        private String lineBreak;
110
111        private LineBreak(String lineBreak) {
112            this.lineBreak = lineBreak;
113        }
114
115        public String getString() {
116            return lineBreak;
117        }
118
119        @Override
120        public String toString() {
121            return "Line break: " + name();
122        }
123
124        public static LineBreak getPlatformLineBreak() {
125            String platformLineBreak = System.getProperty("line.separator");
126            for (LineBreak lb : values()) {
127                if (lb.lineBreak.equals(platformLineBreak)) {
128                    return lb;
129                }
130            }
131            return LineBreak.UNIX;
132        }
133    }
134
135    /**
136     * Specification version. Currently supported 1.0 and 1.1
137     */
138    public enum Version {
139        V1_0(new Integer[] { 1, 0 }), V1_1(new Integer[] { 1, 1 });
140
141        private Integer[] version;
142
143        private Version(Integer[] version) {
144            this.version = version;
145        }
146
147        public int major() { return version[0]; }
148        public int minor() { return version[1]; }
149
150        public String getRepresentation() {
151            return version[0] + "." + version[1];
152        }
153
154        @Override
155        public String toString() {
156            return "Version: " + getRepresentation();
157        }
158    }
159
160    private ScalarStyle defaultStyle = ScalarStyle.PLAIN;
161    private FlowStyle defaultFlowStyle = FlowStyle.AUTO;
162    private boolean canonical = false;
163    private boolean allowUnicode = true;
164    private boolean allowReadOnlyProperties = false;
165    private int indent = 2;
166    private int indicatorIndent = 0;
167    private int bestWidth = 80;
168    private boolean splitLines = true;
169    private LineBreak lineBreak = LineBreak.UNIX;
170    private boolean explicitStart = false;
171    private boolean explicitEnd = false;
172    private TimeZone timeZone = null;
173
174    private Version version = null;
175    private Map<String, String> tags = null;
176    private Boolean prettyFlow = false;
177    private AnchorGenerator anchorGenerator = new NumberAnchorGenerator(0);
178
179    public boolean isAllowUnicode() {
180        return allowUnicode;
181    }
182
183    /**
184     * Specify whether to emit non-ASCII printable Unicode characters.
185     * The default value is true.
186     * When set to false then printable non-ASCII characters (Cyrillic, Chinese etc)
187     * will be not printed but escaped (to support ASCII terminals)
188     *
189     * @param allowUnicode
190     *            if allowUnicode is false then all non-ASCII characters are
191     *            escaped
192     */
193    public void setAllowUnicode(boolean allowUnicode) {
194        this.allowUnicode = allowUnicode;
195    }
196
197    public ScalarStyle getDefaultScalarStyle() {
198        return defaultStyle;
199    }
200
201    /**
202     * Set default style for scalars. See YAML 1.1 specification, 2.3 Scalars
203     * (http://yaml.org/spec/1.1/#id858081)
204     *
205     * @param defaultStyle
206     *            set the style for all scalars
207     */
208    public void setDefaultScalarStyle(ScalarStyle defaultStyle) {
209        if (defaultStyle == null) {
210            throw new NullPointerException("Use ScalarStyle enum.");
211        }
212        this.defaultStyle = defaultStyle;
213    }
214
215    public void setIndent(int indent) {
216        if (indent < Emitter.MIN_INDENT) {
217            throw new YAMLException("Indent must be at least " + Emitter.MIN_INDENT);
218        }
219        if (indent > Emitter.MAX_INDENT) {
220            throw new YAMLException("Indent must be at most " + Emitter.MAX_INDENT);
221        }
222        this.indent = indent;
223    }
224
225    public int getIndent() {
226        return this.indent;
227    }
228
229    public void setIndicatorIndent(int indicatorIndent) {
230        if (indicatorIndent < 0) {
231            throw new YAMLException("Indicator indent must be non-negative.");
232        }
233        if (indicatorIndent > Emitter.MAX_INDENT - 1) {
234            throw new YAMLException("Indicator indent must be at most Emitter.MAX_INDENT-1: " + (Emitter.MAX_INDENT - 1));
235        }
236        this.indicatorIndent = indicatorIndent;
237    }
238
239    public int getIndicatorIndent() {
240        return this.indicatorIndent;
241    }
242
243    public void setVersion(Version version) {
244        this.version = version;
245    }
246
247    public Version getVersion() {
248        return this.version;
249    }
250
251    /**
252     * Force the emitter to produce a canonical YAML document.
253     *
254     * @param canonical
255     *            true produce canonical YAML document
256     */
257    public void setCanonical(boolean canonical) {
258        this.canonical = canonical;
259    }
260
261    public boolean isCanonical() {
262        return this.canonical;
263    }
264
265    /**
266     * Force the emitter to produce a pretty YAML document when using the flow
267     * style.
268     *
269     * @param prettyFlow
270     *            true produce pretty flow YAML document
271     */
272    public void setPrettyFlow(boolean prettyFlow) {
273        this.prettyFlow = prettyFlow;
274    }
275
276    public boolean isPrettyFlow() {
277        return this.prettyFlow;
278    }
279
280    /**
281     * Specify the preferred width to emit scalars. When the scalar
282     * representation takes more then the preferred with the scalar will be
283     * split into a few lines. The default is 80.
284     *
285     * @param bestWidth
286     *            the preferred width for scalars.
287     */
288    public void setWidth(int bestWidth) {
289        this.bestWidth = bestWidth;
290    }
291
292    public int getWidth() {
293        return this.bestWidth;
294    }
295
296    /**
297     * Specify whether to split lines exceeding preferred width for
298     * scalars. The default is true.
299     *
300     * @param splitLines
301     *            whether to split lines exceeding preferred width for scalars.
302     */
303    public void setSplitLines(boolean splitLines) {
304        this.splitLines = splitLines;
305    }
306
307    public boolean getSplitLines() {
308        return this.splitLines;
309    }
310
311    public LineBreak getLineBreak() {
312        return lineBreak;
313    }
314
315    public void setDefaultFlowStyle(FlowStyle defaultFlowStyle) {
316        if (defaultFlowStyle == null) {
317            throw new NullPointerException("Use FlowStyle enum.");
318        }
319        this.defaultFlowStyle = defaultFlowStyle;
320    }
321
322    public FlowStyle getDefaultFlowStyle() {
323        return defaultFlowStyle;
324    }
325
326    /**
327     * Specify the line break to separate the lines. It is platform specific:
328     * Windows - "\r\n", old MacOS - "\r", Unix - "\n". The default value is the
329     * one for Unix.
330     */
331    public void setLineBreak(LineBreak lineBreak) {
332        if (lineBreak == null) {
333            throw new NullPointerException("Specify line break.");
334        }
335        this.lineBreak = lineBreak;
336    }
337
338    public boolean isExplicitStart() {
339        return explicitStart;
340    }
341
342    public void setExplicitStart(boolean explicitStart) {
343        this.explicitStart = explicitStart;
344    }
345
346    public boolean isExplicitEnd() {
347        return explicitEnd;
348    }
349
350    public void setExplicitEnd(boolean explicitEnd) {
351        this.explicitEnd = explicitEnd;
352    }
353
354    public Map<String, String> getTags() {
355        return tags;
356    }
357
358    // TODO should use Tag ???
359    public void setTags(Map<String, String> tags) {
360        this.tags = tags;
361    }
362
363    /**
364     * Report whether read-only JavaBean properties (the ones without setters)
365     * should be included in the YAML document
366     *
367     * @return false when read-only JavaBean properties are not emitted
368     */
369    public boolean isAllowReadOnlyProperties() {
370        return allowReadOnlyProperties;
371    }
372
373    /**
374     * Set to true to include read-only JavaBean properties (the ones without
375     * setters) in the YAML document. By default these properties are not
376     * included to be able to parse later the same JavaBean.
377     *
378     * @param allowReadOnlyProperties
379     *            - true to dump read-only JavaBean properties
380     */
381    public void setAllowReadOnlyProperties(boolean allowReadOnlyProperties) {
382        this.allowReadOnlyProperties = allowReadOnlyProperties;
383    }
384
385    public TimeZone getTimeZone() {
386        return timeZone;
387    }
388
389    /**
390     * Set the timezone to be used for Date. If set to <code>null</code> UTC is
391     * used.
392     */
393    public void setTimeZone(TimeZone timeZone) {
394        this.timeZone = timeZone;
395    }
396
397
398    public AnchorGenerator getAnchorGenerator() {
399        return anchorGenerator;
400    }
401
402    public void setAnchorGenerator(AnchorGenerator anchorGenerator) {
403        this.anchorGenerator = anchorGenerator;
404    }
405}
406