2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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
11 http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.aai.introspection;
23 import java.io.StringReader;
24 import java.io.StringWriter;
25 import java.lang.reflect.Field;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import java.lang.reflect.ParameterizedType;
29 import java.lang.reflect.Type;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.LinkedHashSet;
35 import java.util.List;
39 import javax.xml.bind.JAXBContext;
40 import javax.xml.bind.JAXBException;
41 import javax.xml.bind.Marshaller;
42 import javax.xml.bind.Unmarshaller;
43 import javax.xml.bind.annotation.XmlElement;
44 import javax.xml.transform.stream.StreamSource;
46 import org.eclipse.persistence.jaxb.UnmarshallerProperties;
48 import org.openecomp.aai.annotations.Metadata;
49 import org.openecomp.aai.logging.ErrorLogHelper;
50 import org.openecomp.aai.restcore.MediaType;
51 import org.openecomp.aai.schema.enums.ObjectMetadata;
52 import org.openecomp.aai.schema.enums.PropertyMetadata;
53 import com.google.common.base.CaseFormat;
54 import com.google.common.base.Joiner;
55 import com.google.common.collect.Multimap;
57 public class PojoStrategy extends Introspector {
59 private Object internalObject = null;
60 private PojoInjestor injestor = null;
61 private Multimap<String, String> keyProps = null;
62 private Metadata classLevelMetadata = null;
63 private Version version;
64 private JAXBContext jaxbContext;
65 private Marshaller marshaller;
66 private Unmarshaller unmarshaller;
67 private Set<String> properties = null;
68 private Set<String> keys = null;
69 private Set<String> requiredProperties = null;
71 private boolean isInitialized = false;
73 protected PojoStrategy(Object obj) {
75 className = PojoStrategy.class.getSimpleName();
76 this.internalObject = obj;
77 injestor = new PojoInjestor();
78 classLevelMetadata = obj.getClass().getAnnotation(Metadata.class);
80 version = injestor.getVersion(obj.getClass().getName());
81 jaxbContext = injestor.getContextForVersion(version);
82 super.loader = LoaderFactory.createLoaderForVersion(getModelType(), version);
84 marshaller = jaxbContext.createMarshaller();
85 unmarshaller = jaxbContext.createUnmarshaller();
86 } catch (JAXBException e) {
96 Set<String> properties = new LinkedHashSet<>();
97 Set<String> keys = new LinkedHashSet<>();
98 Set<String> required = new LinkedHashSet<>();
100 Field[] fields = this.internalObject.getClass().getDeclaredFields();
102 for (Field field : fields) {
103 if (!field.getName().equals("any")) {
104 properties.add(covertFieldToOutputFormat(field.getName()));
105 Metadata annotation = field.getAnnotation(Metadata.class);
106 XmlElement xmlAnnotation = field.getAnnotation(XmlElement.class);
107 if (annotation != null) {
108 if (annotation.isKey()) {
109 keys.add(covertFieldToOutputFormat(field.getName()));
112 if (xmlAnnotation != null) {
113 if (xmlAnnotation.required()) {
114 required.add(covertFieldToOutputFormat(field.getName()));
119 properties = Collections.unmodifiableSet(properties);
120 this.properties = properties;
122 keys = Collections.unmodifiableSet(keys);
125 required = Collections.unmodifiableSet(required);
126 this.requiredProperties = required;
129 private String covertFieldToOutputFormat(String propName) {
130 return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName);
134 public boolean hasProperty(String name) {
141 * Gets the value of the property via reflection
143 public Object get(String name) {
144 String getMethodName = "get" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name);
146 return this.internalObject.getClass().getDeclaredMethod(getMethodName).invoke(this.internalObject);
147 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
153 public void set(String name, Object value) {
154 String setMethodName = "set" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name);
156 this.internalObject.getClass().getDeclaredMethod(setMethodName, value.getClass()).invoke(this.internalObject, value);
157 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
158 ErrorLogHelper.logError("AAI_4017", "Error setting name/value pair on POJO: " + e.getMessage());
163 public Set<String> getProperties() {
168 return this.properties;
173 public Set<String> getRequiredProperties() {
178 return this.requiredProperties;
182 public Set<String> getKeys() {
190 public Class<?> getClass(String name) {
194 field = this.internalObject.getClass().getDeclaredField(CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, name));
195 } catch (NoSuchFieldException | SecurityException e) {
200 return field.getType();
203 public Class<?> getGenericTypeClass(String name) {
206 String getMethodName = "get" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name);
207 Method method = internalObject.getClass().getDeclaredMethod(getMethodName);
208 Type t = method.getGenericReturnType();
209 if(t instanceof ParameterizedType) {
210 ParameterizedType pt = (ParameterizedType)t;
211 return ((Class<?>)pt.getActualTypeArguments()[0]);
216 } catch (Exception e) {
222 public String getJavaClassName() {
223 return internalObject.getClass().getName();
227 public Object getUnderlyingObject() {
228 return this.internalObject;
232 public String getName() {
233 String className = internalObject.getClass().getSimpleName();
235 return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
239 protected String findKey() {
240 Set<String> keys = null;
241 keys = this.getKeys();
242 List<String> results = new ArrayList<>();
243 for (String key : keys) {
244 if (this.getType(key).toLowerCase().contains("long")) {
245 key = ((Long)this.getValue(key)).toString();
247 key = (String)this.getValue(key);
252 return Joiner.on("/").join(results);
256 public String marshal(MarshallerProperties properties) {
257 StringWriter result = new StringWriter();
259 if (properties.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)) {
260 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE, "application/json");
261 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT, properties.getIncludeRoot());
262 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, properties.getWrapperAsArrayName());
264 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
265 marshaller.marshal(this.internalObject, result);
266 } catch (JAXBException e) {
267 //e.printStackTrace();
270 return result.toString();
274 public Object clone() {
275 Object result = null;
277 unmarshaller = jaxbContext.createUnmarshaller();
279 unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
280 unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
281 unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
283 result = unmarshaller.unmarshal(new StreamSource(new StringReader(this.marshal(true))), this.internalObject.getClass()).getValue();
284 } catch (JAXBException e) {
285 // TODO Auto-generated catch block
286 //e.printStackTrace();
288 result = IntrospectorFactory.newInstance(getModelType(), result);
293 public String preProcessKey (String key) {
295 //String trimmedRestURI = restURI.replaceAll("/[\\w\\-]+?/[\\w\\-]+?$", "");
296 String[] split = key.split("/");
298 for (i = split.length-1; i >= 0; i--) {
300 if (keyProps.containsKey(split[i])) {
306 result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
313 public ModelType getModelType() {
314 return ModelType.POJO;
318 public String getChildName() {
319 String className = internalObject.getClass().getSimpleName();
320 String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
322 if (this.isContainer()) {
323 lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().iterator().next()).getSimpleName());
330 public Map<PropertyMetadata, String> getPropertyMetadata(String prop) {
332 Map<PropertyMetadata, String> result = new HashMap<>();
334 f = internalObject.getClass().getField(prop);
335 Metadata m = f.getAnnotation(Metadata.class);
337 Field[] fields = m.getClass().getFields();
339 for (Field field : fields) {
340 fieldName = field.getName();
341 if (fieldName.equals("isAbstract")) {
342 fieldName = "abstract";
343 } else if (fieldName.equals("extendsFrom")) {
344 fieldName = "extends";
346 fieldName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, fieldName);
347 result.put(PropertyMetadata.valueOf(fieldName), (String)field.get(m));
350 } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
351 // TODO Auto-generated catch block
358 public String getObjectId() {
359 // TODO Auto-generated method stub
364 public String getMetadata(ObjectMetadata metadataName) {
367 if (ObjectMetadata.ABSTRACT.equals(metadataName)) {
368 methodName = "isAbstract";
369 } else if (ObjectMetadata.EXTENDS.equals(metadataName)) {
370 methodName = "extendsFrom";
372 methodName = metadataName.toString();
376 value = (String)this.classLevelMetadata.getClass().getMethod(methodName).invoke(classLevelMetadata);
377 } catch (IllegalArgumentException | IllegalAccessException | SecurityException | InvocationTargetException | NoSuchMethodException e) {
385 public Version getVersion() {
386 // TODO Auto-generated method stub