Reduce the number of problems in aai-common by removing unused imports
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / introspection / MoxyStrategy.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.aai.introspection;
22
23 import com.google.common.base.CaseFormat;
24 import com.google.common.base.Joiner;
25
26 import java.io.StringWriter;
27 import java.io.UnsupportedEncodingException;
28 import java.util.*;
29 import java.util.Map.Entry;
30
31 import javax.xml.bind.JAXBException;
32 import javax.xml.bind.Marshaller;
33
34 import org.eclipse.persistence.descriptors.ClassDescriptor;
35 import org.eclipse.persistence.dynamic.DynamicEntity;
36 import org.eclipse.persistence.dynamic.DynamicType;
37 import org.eclipse.persistence.exceptions.DynamicException;
38 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
39 import org.eclipse.persistence.mappings.DatabaseMapping;
40 import org.eclipse.persistence.oxm.XMLField;
41 import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
42 import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping;
43 import org.onap.aai.config.SpringContextAware;
44 import org.onap.aai.logging.LogFormatTools;
45 import org.onap.aai.restcore.MediaType;
46 import org.onap.aai.schema.enums.ObjectMetadata;
47 import org.onap.aai.schema.enums.PropertyMetadata;
48 import org.onap.aai.setup.SchemaVersion;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51 import org.springframework.web.util.UriUtils;
52
53 public class MoxyStrategy extends Introspector {
54
55     private static final Logger LOGGER = LoggerFactory.getLogger(MoxyStrategy.class);
56     private DynamicEntity internalObject = null;
57     private DynamicType internalType = null;
58     private DynamicJAXBContext jaxbContext = null;
59     private ClassDescriptor cd = null;
60     private SchemaVersion version = null;
61     private Set<String> properties = null;
62     private Set<String> keys = null;
63     private Set<String> requiredProperties = null;
64
65     private boolean isInitialized = false;
66
67     protected MoxyStrategy(Object obj) {
68         super(obj);
69         /* must look up the correct jaxbcontext for this object */
70         className = MoxyStrategy.class.getSimpleName();
71         internalObject = (DynamicEntity) obj;
72         version = nodeIngestor.getVersionFromClassName(internalObject.getClass().getName());
73         super.loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(getModelType(), version);
74         jaxbContext = nodeIngestor.getContextForVersion(version);
75         String simpleName = internalObject.getClass().getName();
76         internalType = jaxbContext.getDynamicType(simpleName);
77
78         cd = internalType.getDescriptor();
79     }
80
81     private void init() {
82         isInitialized = true;
83
84         Set<String> props = new LinkedHashSet<>();
85         for (String s : internalType.getPropertiesNames()) {
86             String value = caseFormatStore.fromLowerCamelToLowerHyphen(s).orElseGet(() -> {
87                 LOGGER.debug("Unable to find {} in the store from lower camel to lower hyphen", s);
88                 return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, s);
89             });
90             props.add(value);
91
92         }
93         props = Collections.unmodifiableSet(props);
94         this.properties = props;
95
96         Set<String> requiredProps = new LinkedHashSet<>();
97         for (DatabaseMapping dm : cd.getMappings()) {
98             if (dm.getField() instanceof XMLField) {
99                 XMLField x = (XMLField) dm.getField();
100                 if (x != null && x.isRequired()) {
101                     requiredProps.add(this.removeXPathDescriptor(x.getName()));
102                 }
103             }
104         }
105         requiredProps = Collections.unmodifiableSet(requiredProps);
106         this.requiredProperties = requiredProps;
107
108         Set<String> keys = new LinkedHashSet<>();
109
110         for (String name : internalType.getDescriptor().getPrimaryKeyFieldNames()) {
111             keys.add(this.removeXPathDescriptor(name));
112         }
113         keys = Collections.unmodifiableSet(keys);
114         this.keys = keys;
115
116     }
117
118     @Override
119     public boolean hasProperty(String name) {
120         String convertedName = convertPropertyName(name);
121
122         return internalType.containsProperty(convertedName);
123     }
124
125     @Override
126     public Object get(String name) {
127         return internalObject.get(name);
128     }
129
130     @Override
131     public void set(String name, Object obj) {
132
133         internalObject.set(name, obj);
134     }
135
136     @Override
137     public Set<String> getProperties() {
138
139         if (!isInitialized) {
140             init();
141         }
142
143         return this.properties;
144
145     }
146
147     @Override
148     public Set<String> getRequiredProperties() {
149
150         if (!isInitialized) {
151             init();
152         }
153
154         return this.requiredProperties;
155     }
156
157     @Override
158     public Set<String> getKeys() {
159
160         if (!isInitialized) {
161             init();
162         }
163
164         return this.keys;
165     }
166
167     @Override
168     public Map<PropertyMetadata, String> getPropertyMetadata(String prop) {
169         String propName = this.convertPropertyName(prop);
170         DatabaseMapping mapping = cd.getMappingForAttributeName(propName);
171         Map<PropertyMetadata, String> result = new HashMap<>();
172         if (mapping != null) {
173             Set<Entry> entrySet = mapping.getProperties().entrySet();
174             for (Entry<?, ?> entry : entrySet) {
175                 result.put(
176                         PropertyMetadata.valueOf(
177                                 CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, (String) entry.getKey())),
178                         (String) entry.getValue());
179             }
180         }
181
182         return result;
183     }
184
185     @Override
186     public String getJavaClassName() {
187         return internalObject.getClass().getName();
188     }
189
190     @Override
191     public Class<?> getClass(String name) {
192         name = convertPropertyName(name);
193         Class<?> resultClass = null;
194         try {
195             if (internalType.getPropertyType(name) == null) {
196                 if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
197                     resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
198
199                 } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
200                     resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
201                 } else {
202                     ClassDescriptor referenceDiscriptor = cd.getMappingForAttributeName(name).getReferenceDescriptor();
203                     if (referenceDiscriptor != null) {
204                         resultClass = referenceDiscriptor.getJavaClass();
205                     } else {
206                         resultClass = Object.class;
207                     }
208                 }
209             } else {
210                 resultClass = internalType.getPropertyType(name);
211             }
212         } catch (DynamicException e) {
213             // property doesn't exist
214         }
215         return resultClass;
216     }
217
218     @Override
219     public Class<?> getGenericTypeClass(String name) {
220         name = convertPropertyName(name);
221         Class<?> resultClass = null;
222         if (internalType.getPropertyType(name) == null) {
223             if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
224                 resultClass = cd.getMappingForAttributeName(name).getFields().get(0).getType();
225
226             } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
227                 resultClass = cd.getMappingForAttributeName(name).getReferenceDescriptor().getJavaClass();
228             }
229         }
230
231         return resultClass;
232     }
233
234     @Override
235     public Object getUnderlyingObject() {
236         return this.internalObject;
237     }
238
239     @Override
240     public String getChildName() {
241
242         String className = internalObject.getClass().getSimpleName();
243         String lowerHyphen = caseFormatStore.fromUpperCamelToLowerHyphen(className).orElseGet(() -> {
244             LOGGER.debug("Unable to find {} in the store for upper camel to lower hyphen", className);
245             return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
246         });
247
248         if (this.isContainer()) {
249             String upperCamel = this.getGenericTypeClass(this.getProperties().iterator().next()).getSimpleName();
250
251             lowerHyphen = caseFormatStore.fromUpperCamelToLowerHyphen(upperCamel).orElseGet(() -> {
252                 LOGGER.debug("Unable to find {} in the store for upper camel to lower hyphen", upperCamel);
253                 return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, upperCamel);
254             });
255         }
256
257         return lowerHyphen;
258     }
259
260     @Override
261     public String getName() {
262         String className = internalObject.getClass().getSimpleName();
263         return caseFormatStore.fromUpperCamelToLowerHyphen(className).orElseGet(() -> {
264             LOGGER.debug("Unable to find {} in the store for upper camel to lower hyphen", className);
265             return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
266         });
267     }
268
269     @Override
270     public String getObjectId() throws UnsupportedEncodingException {
271         String result = "";
272         String container = this.getMetadata(ObjectMetadata.CONTAINER);
273         if (this.isContainer()) {
274             result += "/" + this.getName();
275         } else {
276
277             if (container != null) {
278                 result += "/" + container;
279             }
280             result += "/" + this.getDbName() + "/" + this.findKey();
281
282         }
283
284         return result;
285     }
286
287     @Override
288     protected String findKey() throws UnsupportedEncodingException {
289         Set<String> keys = null;
290         keys = this.getKeys();
291         List<String> results = new ArrayList<>();
292         for (String key : keys) {
293             String value = UriUtils.encode(this.getValue(key).toString(), "UTF-8");
294             results.add(value);
295         }
296
297         return Joiner.on("/").join(results);
298     }
299
300     @Override
301     public String preProcessKey(String key) {
302         String result = "";
303         String[] split = key.split("/");
304         int i = 0;
305         for (i = split.length - 1; i >= 0; i--) {
306
307             if (jaxbContext.getDynamicType(split[i]) != null) {
308                 break;
309
310             }
311
312         }
313         result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
314
315         return result;
316
317     }
318
319     @Override
320     public String marshal(MarshallerProperties properties) {
321         StringWriter result = new StringWriter();
322         try {
323             Marshaller marshaller = jaxbContext.createMarshaller();
324             if (properties.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)) {
325                 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE,
326                         "application/json");
327                 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT,
328                         properties.getIncludeRoot());
329                 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME,
330                         properties.getWrapperAsArrayName());
331                 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS,
332                         false);
333             }
334
335             marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
336             marshaller.marshal(this.internalObject, result);
337         } catch (JAXBException e) {
338             LOGGER.warn("Encountered an jaxb exception during marshalling ", LogFormatTools.getStackTop(e));
339         }
340
341         return result.toString();
342     }
343
344     @Override
345     public ModelType getModelType() {
346         return ModelType.MOXY;
347     }
348
349     private String removeXPathDescriptor(String name) {
350
351         return name.replaceAll("/text\\(\\)", "");
352     }
353
354     @Override
355     public String getMetadata(ObjectMetadata name) {
356
357         return (String) cd.getProperty(name.toString());
358     }
359
360     @Override
361     public SchemaVersion getVersion() {
362
363         return this.version;
364     }
365 }