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