View Javadoc
1   package net.avcompris.commons3.yaml;
2   
3   import static com.google.common.base.Preconditions.checkArgument;
4   import static com.google.common.base.Preconditions.checkNotNull;
5   import static com.google.common.base.Preconditions.checkState;
6   import static java.nio.charset.StandardCharsets.UTF_8;
7   
8   import java.io.BufferedInputStream;
9   import java.io.File;
10  import java.io.FileInputStream;
11  import java.io.IOException;
12  import java.io.InputStream;
13  import java.io.InputStreamReader;
14  import java.io.Reader;
15  import java.io.StringReader;
16  import java.util.Date;
17  import java.util.List;
18  import java.util.Map;
19  import java.util.stream.Collectors;
20  
21  import javax.annotation.Nullable;
22  
23  import org.apache.commons.lang3.NotImplementedException;
24  // import org.yaml.snakeyaml.constructor.SafeConstructor;
25  
26  public abstract class YamlUtils {
27  
28  	public static Yaml loadYaml(final InputStream is) throws IOException {
29  
30  		checkNotNull(is, "is");
31  
32  		// final org.yaml.snakeyaml.Yaml snakeYaml = new org.yaml.snakeyaml.Yaml(new SafeConstructor());
33  
34  		// @SuppressWarnings("unchecked")
35  		// final Map<Object, Object> m = (Map<Object, Object>) snakeYaml.load(is);
36  
37  		final Map<Object, Object> map;
38  
39  		try (BufferedInputStream bis = new BufferedInputStream(is)) {
40  
41  			try (Reader reader = new InputStreamReader(bis, UTF_8)) {
42  
43  				map = new YamlLoader().load(reader);
44  			}
45  		}
46  
47  		return new YamlImpl(map);
48  	}
49  
50  	public static Yaml loadYaml(final File yamlFile) throws IOException {
51  
52  		checkNotNull(yamlFile, "yamlFile");
53  
54  		try (InputStream is = new FileInputStream(yamlFile)) {
55  
56  			return loadYaml(is);
57  		}
58  	}
59  
60  	public static Yaml loadYaml(final String yamlContent) throws IOException {
61  
62  		checkNotNull(yamlContent, "yamlContent");
63  
64  		// final org.yaml.snakeyaml.Yaml snakeYaml = new org.yaml.snakeyaml.Yaml(new SafeConstructor());
65  
66  		// @SuppressWarnings("unchecked")
67  		// final Map<Object, Object> map = (Map<Object, Object>) snakeYaml.load(yamlContent);
68  
69  		final Map<Object, Object> map;
70  
71  		try (Reader reader = new StringReader(yamlContent)) {
72  
73  			map = new YamlLoader().load(reader);
74  		}
75  
76  		return new YamlImpl(map);
77  	}
78  
79  	private static final class YamlImpl implements Yaml {
80  
81  		private static final Yaml NULL = new YamlImpl();
82  
83  		@Nullable
84  		private final Map<Object, Object> map;
85  
86  		@Nullable
87  		private final List<Object> list;
88  
89  		@Nullable
90  		private final String s;
91  
92  		@Nullable
93  		private final Integer n;
94  
95  		@Nullable
96  		private final Long l;
97  
98  		@Nullable
99  		private final Boolean b;
100 
101 		@Nullable
102 		private final Date date;
103 
104 		YamlImpl(@Nullable final Map<Object, Object> map) {
105 
106 			this.map = map;
107 			this.list = null;
108 			this.s = null;
109 			this.n = null;
110 			this.l = null;
111 			this.b = null;
112 			this.date = null;
113 		}
114 
115 		YamlImpl(final List<Object> list) {
116 
117 			this.map = null;
118 			this.list = checkNotNull(list, "list");
119 			this.s = null;
120 			this.n = null;
121 			this.l = null;
122 			this.b = null;
123 			this.date = null;
124 		}
125 
126 		YamlImpl(final String s) {
127 
128 			this.map = null;
129 			this.list = null;
130 			this.s = checkNotNull(s, "s");
131 			this.n = null;
132 			this.l = null;
133 			this.b = null;
134 			this.date = null;
135 		}
136 
137 		YamlImpl(final int n) {
138 
139 			this.map = null;
140 			this.list = null;
141 			this.s = null;
142 			this.n = n;
143 			this.l = (long) n;
144 			this.b = null;
145 			this.date = null;
146 		}
147 
148 		YamlImpl(final long l) {
149 
150 			this.map = null;
151 			this.list = null;
152 			this.s = null;
153 			this.n = null;
154 			this.l = l;
155 			this.b = null;
156 			this.date = null;
157 		}
158 
159 		YamlImpl(final boolean b) {
160 
161 			this.map = null;
162 			this.list = null;
163 			this.s = null;
164 			this.n = null;
165 			this.l = null;
166 			this.b = b;
167 			this.date = null;
168 		}
169 
170 		YamlImpl(final Date date) {
171 
172 			this.map = null;
173 			this.list = null;
174 			this.s = null;
175 			this.n = null;
176 			this.l = null;
177 			this.b = null;
178 			this.date = checkNotNull(date, "date");
179 		}
180 
181 		private YamlImpl() {
182 
183 			this.map = null;
184 			this.list = null;
185 			this.s = null;
186 			this.n = null;
187 			this.l = null;
188 			this.b = null;
189 			this.date = null;
190 		}
191 
192 		@Override
193 		public Iterable<Object> keys() {
194 
195 			return map.keySet();
196 		}
197 
198 		@Override
199 		public boolean has(final Object key) {
200 
201 			checkNotNull(key, "key");
202 
203 			return map != null && map.containsKey(key);
204 		}
205 
206 		@Override
207 		public Yaml get(final Object key) {
208 
209 			checkNotNull(key, "key");
210 
211 			checkState(map != null, "Internal map should not be null");
212 
213 			checkArgument(map.containsKey(key), "key: %s", key);
214 
215 			final Object value = map.get(key);
216 
217 			if (value == null) {
218 
219 				return YamlImpl.NULL;
220 
221 			} else {
222 
223 				return toYaml(value);
224 			}
225 		}
226 
227 		private static Yaml toYaml(final Object value) {
228 
229 			checkNotNull(value, "value");
230 
231 			if (value instanceof Map) {
232 
233 				@SuppressWarnings("unchecked")
234 				final Map<Object, Object> map = (Map<Object, Object>) value;
235 
236 				return new YamlImpl(map);
237 
238 			} else if (value instanceof List) {
239 
240 				@SuppressWarnings("unchecked")
241 				final List<Object> list = (List<Object>) value;
242 
243 				return new YamlImpl(list);
244 
245 			} else if (value instanceof String) {
246 
247 				final String s = (String) value;
248 
249 				return new YamlImpl(s);
250 
251 			} else if (value instanceof Integer) {
252 
253 				final int n = (Integer) value;
254 
255 				return new YamlImpl(n);
256 
257 			} else if (value instanceof Long) {
258 
259 				final long l = (Long) value;
260 
261 				return new YamlImpl(l);
262 
263 			} else if (value instanceof Boolean) {
264 
265 				final boolean b = (Boolean) value;
266 
267 				return new YamlImpl(b);
268 
269 			} else if (value instanceof Date) {
270 
271 				final Date date = (Date) value;
272 
273 				return new YamlImpl(date);
274 			}
275 
276 			throw new NotImplementedException("value.class: " + value.getClass());
277 		}
278 
279 		@Override
280 		public Iterable<String> keysAsStrings() {
281 
282 			return map.keySet().stream() //
283 					.map(key -> key.toString()) //
284 					.sorted() //
285 					.collect(Collectors.toList());
286 		}
287 
288 		@Override
289 		public boolean isArray() {
290 
291 			return list != null;
292 		}
293 
294 		@Override
295 		public boolean isMap() {
296 
297 			return map != null;
298 		}
299 
300 		@Override
301 		public boolean isString() {
302 
303 			return s != null;
304 		}
305 
306 		@Override
307 		public boolean isInt() {
308 
309 			return n != null;
310 		}
311 
312 		@Override
313 		public boolean isBoolean() {
314 
315 			return b != null;
316 		}
317 
318 		@Override
319 		public Date asDate() {
320 
321 			checkState(date != null, "Internal date should not be null");
322 
323 			return date;
324 		}
325 
326 		@Override
327 		public String asString() {
328 
329 			if (date != null) {
330 
331 				throw new NotImplementedException("date: " + date);
332 
333 			} else if (n != null) {
334 
335 				return Integer.toString(n);
336 
337 			} else if (l != null) {
338 
339 				return Long.toString(l);
340 
341 			} else if (b != null) {
342 
343 				return Boolean.toString(b);
344 			}
345 
346 			checkState(s != null, "Internal string should not be null");
347 
348 			return s;
349 		}
350 
351 		@Override
352 		public int asInt() {
353 
354 			if (date != null) {
355 
356 				throw new NotImplementedException("date: " + date);
357 			}
358 
359 			checkState(n != null, "Internal int should not be null");
360 
361 			return n;
362 		}
363 
364 		@Override
365 		public long asLong() {
366 
367 			if (date != null) {
368 
369 				throw new NotImplementedException("date: " + date);
370 
371 			} else if (l != null) {
372 
373 				return l;
374 
375 			} else if (n != null) {
376 
377 				return n;
378 			}
379 
380 			throw new IllegalStateException("Internal long should not be null");
381 		}
382 
383 		@Override
384 		public boolean asBoolean() {
385 
386 			if (date != null) {
387 				throw new NotImplementedException("date: " + date);
388 			}
389 
390 			if (b != null) {
391 
392 				return b;
393 			}
394 
395 			if (s != null) {
396 
397 				if ("yes".equals(s)) {
398 
399 					return true;
400 
401 				} else if ("no".equals(s)) {
402 
403 					return false;
404 
405 				} else {
406 
407 					throw new NotImplementedException("Cannot parse string to boolean: " + s);
408 				}
409 			}
410 
411 			throw new IllegalStateException("Internal boolean should not be null");
412 		}
413 
414 		@Override
415 		public Iterable<Yaml> items() {
416 
417 			return list.stream() //
418 					.map(item -> toYaml(item)) //
419 					.collect(Collectors.toList());
420 		}
421 
422 		@Override
423 		public String toString() {
424 
425 			final StringBuilder sb = new StringBuilder("{");
426 
427 			if (s != null) {
428 				sb.append(sb.length() == 1 ? "" : ", ").append("s: ").append(s);
429 			}
430 			if (n != null) {
431 				sb.append(sb.length() == 1 ? "" : ", ").append("n: ").append(n);
432 			}
433 			if (l != null) {
434 				sb.append(sb.length() == 1 ? "" : ", ").append("l: ").append(l);
435 			}
436 			if (b != null) {
437 				sb.append(sb.length() == 1 ? "" : ", ").append("b: ").append(b);
438 			}
439 			if (date != null) {
440 				sb.append(sb.length() == 1 ? "" : ", ").append("date: ").append(date);
441 			}
442 			if (list != null) {
443 				sb.append(sb.length() == 1 ? "" : ", ").append("list: ").append(list);
444 			}
445 			if (map != null) {
446 				sb.append(sb.length() == 1 ? "" : ", ").append("map: ").append(map);
447 			}
448 
449 			return sb.append("}").toString();
450 		}
451 	}
452 }