Fix checkstyle violations in sdc-main/common
[sdc.git] / common / onap-tosca-datatype / src / main / java / org / onap / sdc / tosca / services / YamlUtil.java
1 /*
2  * Copyright © 2016-2017 European Support Limited
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
17 package org.onap.sdc.tosca.services;
18
19 import org.yaml.snakeyaml.DumperOptions;
20 import org.yaml.snakeyaml.TypeDescription;
21 import org.yaml.snakeyaml.Yaml;
22 import org.yaml.snakeyaml.constructor.Constructor;
23 import org.yaml.snakeyaml.introspector.BeanAccess;
24 import org.yaml.snakeyaml.introspector.Property;
25 import org.yaml.snakeyaml.introspector.PropertyUtils;
26 import org.yaml.snakeyaml.nodes.MappingNode;
27 import org.yaml.snakeyaml.nodes.NodeTuple;
28 import org.yaml.snakeyaml.nodes.Tag;
29 import org.yaml.snakeyaml.parser.ParserException;
30 import org.yaml.snakeyaml.representer.Representer;
31
32 import java.beans.IntrospectionException;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.util.AbstractMap;
36 import java.util.LinkedHashMap;
37 import java.util.LinkedHashSet;
38 import java.util.Map;
39 import java.util.Set;
40
41 /**
42  * The type Yaml util.
43  */
44 @SuppressWarnings("unchecked")
45 public class YamlUtil {
46
47   private static final String DEFAULT = "default";
48   private static final String DEFAULT_STR = "_default";
49
50   /**
51    * Yaml to object t.
52    *
53    * @param <T>         the type parameter
54    * @param yamlContent the yaml content
55    * @param typClass    the t class
56    * @return the t
57    */
58   public <T> T yamlToObject(String yamlContent, Class<T> typClass) {
59     Constructor constructor = getConstructor(typClass);
60     constructor.setPropertyUtils(getPropertyUtils());
61     TypeDescription yamlFileDescription = new TypeDescription(typClass);
62     constructor.addTypeDescription(yamlFileDescription);
63     Yaml yaml = new Yaml(constructor);
64     T yamlObj = (T) yaml.load(yamlContent);
65     //noinspection ResultOfMethodCallIgnored
66     yamlObj.toString();
67     return yamlObj;
68   }
69
70   public InputStream loadYamlFileIs(String yamlFullFileName) {
71     return YamlUtil.class.getResourceAsStream(yamlFullFileName);
72   }
73
74   /**
75    * Yaml to object t.
76    *
77    * @param <T>         the type parameter
78    * @param yamlContent the yaml content
79    * @param typClass    the t class
80    * @return the t
81    */
82   public <T> T yamlToObject(InputStream yamlContent, Class<T> typClass) {
83     try {
84       Constructor constructor = getConstructor(typClass);
85       constructor.setPropertyUtils(getPropertyUtils());
86       TypeDescription yamlFileDescription = new TypeDescription(typClass);
87       constructor.addTypeDescription(yamlFileDescription);
88       Yaml yaml = new Yaml(constructor);
89       T yamlObj = (T) yaml.load(yamlContent);
90       if (yamlObj != null) {
91         //noinspection ResultOfMethodCallIgnored
92         yamlObj.toString();
93         return yamlObj;
94       } else {
95         throw new RuntimeException();
96       }
97     } catch (Exception exception) {
98       throw new RuntimeException(exception);
99     } finally {
100       try {
101         if (yamlContent != null) {
102           yamlContent.close();
103         }
104       } catch (IOException ignore) {
105         //do nothing
106       }
107     }
108   }
109
110
111   /**
112    * Gets constructor.
113    *
114    * @param <T>      the type parameter
115    * @param typClass the t class
116    * @return the constructor
117    */
118   public <T> Constructor getConstructor(Class<T> typClass) {
119     return new StrictMapAppenderConstructor(typClass);
120   }
121
122   /**
123    * Gets property utils.
124    *
125    * @return the property utils
126    */
127   protected PropertyUtils getPropertyUtils() {
128     return new MyPropertyUtils();
129   }
130
131
132   /**
133    * Yaml to map map.
134    *
135    * @param yamlContent the yaml content
136    * @return the map
137    */
138   public Map<String, LinkedHashMap<String, Object>> yamlToMap(InputStream yamlContent) {
139     Yaml yaml = new Yaml();
140     return (Map<String, LinkedHashMap<String, Object>>) yaml.load(yamlContent);
141   }
142
143   /**
144    * Object to yaml string.
145    * @param obj the obj
146    * @return the string
147    */
148   public String objectToYaml(Object obj) {
149     DumperOptions options = new DumperOptions();
150     options.setPrettyFlow(true);
151     options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
152     Representer representer = new CustomRepresenter();
153     representer.addClassTag(obj.getClass(), Tag.MAP);
154     representer.setPropertyUtils(new MyPropertyUtils());
155
156     Yaml yaml = new Yaml(representer, options);
157     return yaml.dump(obj);
158   }
159
160   /**
161    * Is yaml file content valid boolean.
162    *
163    * @param yamlFullFileName the yaml full file name
164    * @return the boolean
165    */
166   public boolean isYamlFileContentValid(String yamlFullFileName) {
167     Yaml yaml = new Yaml();
168     try {
169       Object loadResult = yaml.load(yamlFullFileName);
170       return loadResult != null;
171     } catch (Exception exception) {
172       return false;
173     }
174   }
175
176
177   private class CustomRepresenter extends Representer {
178     @Override
179     protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
180       //remove the bean type from the output yaml (!! ...)
181       if (!classTags.containsKey(javaBean.getClass())) {
182         addClassTag(javaBean.getClass(), Tag.MAP);
183       }
184
185       return super.representJavaBean(properties, javaBean);
186     }
187
188     @Override
189     protected NodeTuple representJavaBeanProperty(Object javaBean, Property property,
190                                                   Object propertyValue, Tag customTag) {
191       if (propertyValue == null) {
192         return null;
193       } else {
194         NodeTuple defaultNode =
195             super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
196
197         return DEFAULT_STR.equals(property.getName())
198             ? new NodeTuple(representData(DEFAULT), defaultNode.getValueNode())
199             : defaultNode;
200       }
201     }
202   }
203
204
205   /**
206    * The type My property utils.
207    */
208   public class MyPropertyUtils extends PropertyUtils {
209     //Unsorted properties
210     @Override
211     protected Set<Property> createPropertySet(Class<? extends Object> type, BeanAccess bnAccess)
212         throws IntrospectionException {
213       return new LinkedHashSet<>(getPropertiesMap(type,
214           BeanAccess.FIELD).values());
215     }
216
217     @Override
218     public Property getProperty(Class<?> type, String name) throws IntrospectionException {
219       String updatedName = name;
220       if (DEFAULT.equals(updatedName)) {
221         updatedName = DEFAULT_STR;
222       }
223       return super.getProperty(type, updatedName);
224     }
225
226   }
227
228   /**
229    * The type Strict map appender constructor.
230    */
231   protected class StrictMapAppenderConstructor extends Constructor {
232
233     /**
234      * Instantiates a new Strict map appender constructor.
235      *
236      * @param theRoot the the root
237      */
238     public StrictMapAppenderConstructor(Class<?> theRoot) {
239       super(theRoot);
240     }
241
242     @Override
243     protected Map<Object, Object> createDefaultMap() {
244       final Map<Object, Object> delegate = super.createDefaultMap();
245       return new AbstractMap<Object, Object>() {
246         @Override
247         public Object put(Object key, Object value) {
248           if (delegate.containsKey(key)) {
249             throw new IllegalStateException("duplicate key: " + key);
250           }
251           return delegate.put(key, value);
252         }
253
254         @Override
255         public Set<Entry<Object, Object>> entrySet() {
256           return delegate.entrySet();
257         }
258       };
259     }
260
261     @Override
262     protected Map<Object, Object> constructMapping(MappingNode node) {
263       try {
264         return super.constructMapping(node);
265       } catch (IllegalStateException exception) {
266         throw new ParserException("while parsing MappingNode",
267             node.getStartMark(), exception.getMessage(),
268             node.getEndMark());
269       }
270     }
271   }
272 }