2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 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=========================================================
20 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 package org.onap.aai.introspection;
24 import com.att.eelf.configuration.EELFLogger;
25 import com.att.eelf.configuration.EELFManager;
26 import com.google.common.base.CaseFormat;
27 import com.google.common.base.Joiner;
28 import com.google.common.collect.Multimap;
29 import org.eclipse.persistence.jaxb.UnmarshallerProperties;
30 import org.onap.aai.annotations.Metadata;
31 import org.onap.aai.logging.ErrorLogHelper;
32 import org.onap.aai.restcore.MediaType;
33 import org.onap.aai.schema.enums.ObjectMetadata;
34 import org.onap.aai.schema.enums.PropertyMetadata;
36 import javax.xml.bind.JAXBContext;
37 import javax.xml.bind.JAXBException;
38 import javax.xml.bind.Marshaller;
39 import javax.xml.bind.Unmarshaller;
40 import javax.xml.bind.annotation.XmlElement;
41 import javax.xml.transform.stream.StreamSource;
42 import java.io.StringReader;
43 import java.io.StringWriter;
44 import java.lang.reflect.*;
47 public class PojoStrategy extends Introspector {
48 private static final EELFLogger LOGGER2 = EELFManager.getInstance().getLogger(PojoStrategy.class);
50 private Object internalObject = null;
51 private PojoInjestor injestor = null;
52 private Multimap<String, String> keyProps = null;
53 private Metadata classLevelMetadata = null;
54 private Version version;
55 private JAXBContext jaxbContext;
56 private Marshaller marshaller;
57 private Unmarshaller unmarshaller;
58 private Set<String> properties = null;
59 private Set<String> keys = null;
60 private Set<String> requiredProperties = null;
62 private boolean isInitialized = false;
64 protected PojoStrategy(Object obj) {
66 className = PojoStrategy.class.getSimpleName();
67 this.internalObject = obj;
68 injestor = new PojoInjestor();
69 classLevelMetadata = obj.getClass().getAnnotation(Metadata.class);
71 version = injestor.getVersion(obj.getClass().getName());
72 jaxbContext = injestor.getContextForVersion(version);
73 super.loader = LoaderFactory.createLoaderForVersion(getModelType(), version);
75 marshaller = jaxbContext.createMarshaller();
76 unmarshaller = jaxbContext.createUnmarshaller();
77 } catch (JAXBException e) {
78 LOGGER2.error(e.getMessage(),e);
87 Set<String> properties = new LinkedHashSet<>();
88 Set<String> keys = new LinkedHashSet<>();
89 Set<String> required = new LinkedHashSet<>();
91 Field[] fields = this.internalObject.getClass().getDeclaredFields();
93 for (Field field : fields) {
94 if (!field.getName().equals("any")) {
95 properties.add(covertFieldToOutputFormat(field.getName()));
96 Metadata annotation = field.getAnnotation(Metadata.class);
97 XmlElement xmlAnnotation = field.getAnnotation(XmlElement.class);
98 if (annotation != null) {
99 if (annotation.isKey()) {
100 keys.add(covertFieldToOutputFormat(field.getName()));
103 if (xmlAnnotation != null) {
104 if (xmlAnnotation.required()) {
105 required.add(covertFieldToOutputFormat(field.getName()));
110 properties = Collections.unmodifiableSet(properties);
111 this.properties = properties;
113 keys = Collections.unmodifiableSet(keys);
116 required = Collections.unmodifiableSet(required);
117 this.requiredProperties = required;
120 private String covertFieldToOutputFormat(String propName) {
121 return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, propName);
125 public boolean hasProperty(String name) {
132 * Gets the value of the property via reflection
134 public Object get(String name) {
135 String getMethodName = "get" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name);
137 return this.internalObject.getClass().getDeclaredMethod(getMethodName).invoke(this.internalObject);
138 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
139 LOGGER2.error(e.getMessage(),e);
145 public void set(String name, Object value) {
146 String setMethodName = "set" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, name);
148 this.internalObject.getClass().getDeclaredMethod(setMethodName, value.getClass()).invoke(this.internalObject, value);
149 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
150 ErrorLogHelper.logError("AAI_4017", "Error setting name/value pair on POJO: " + e.getMessage());
155 public Set<String> getProperties() {
160 return this.properties;
165 public Set<String> getRequiredProperties() {
170 return this.requiredProperties;
174 public Set<String> getKeys() {
182 public Class<?> getClass(String name) {
186 field = this.internalObject.getClass().getDeclaredField(CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, name));
187 } catch (NoSuchFieldException | SecurityException e) {
188 LOGGER2.error(e.getMessage(),e);
192 return field.getType();
195 public Class<?> getGenericTypeClass(String name) {
198 String getMethodName = "get" + CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, name);
199 Method method = internalObject.getClass().getDeclaredMethod(getMethodName);
200 Type t = method.getGenericReturnType();
201 if(t instanceof ParameterizedType) {
202 ParameterizedType pt = (ParameterizedType)t;
203 return ((Class<?>)pt.getActualTypeArguments()[0]);
208 } catch (Exception e) {
209 LOGGER2.error(e.getMessage(),e);
215 public String getJavaClassName() {
216 return internalObject.getClass().getName();
220 public Object getUnderlyingObject() {
221 return this.internalObject;
225 public String getName() {
226 String className = internalObject.getClass().getSimpleName();
228 return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
232 protected String findKey() {
233 Set<String> keys = null;
234 keys = this.getKeys();
235 List<String> results = new ArrayList<>();
236 for (String key : keys) {
237 if (this.getType(key).toLowerCase().contains("long")) {
238 key = ((Long)this.getValue(key)).toString();
240 key = (String)this.getValue(key);
245 return Joiner.on("/").join(results);
249 public String marshal(MarshallerProperties properties) {
250 StringWriter result = new StringWriter();
252 if (properties.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)) {
253 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE, "application/json");
254 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT, properties.getIncludeRoot());
255 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, properties.getWrapperAsArrayName());
257 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
258 marshaller.marshal(this.internalObject, result);
259 } catch (JAXBException e) {
260 LOGGER2.error(e.getMessage(),e);
263 return result.toString();
267 public Object clone() {
268 Object result = null;
270 unmarshaller = jaxbContext.createUnmarshaller();
272 unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
273 unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
274 unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
276 result = unmarshaller.unmarshal(new StreamSource(new StringReader(this.marshal(true))), this.internalObject.getClass()).getValue();
277 } catch (JAXBException e) {
278 LOGGER2.error(e.getMessage(),e);
280 result = IntrospectorFactory.newInstance(getModelType(), result);
285 public String preProcessKey (String key) {
287 //String trimmedRestURI = restURI.replaceAll("/[\\w\\-]+?/[\\w\\-]+?$", "");
288 String[] split = key.split("/");
290 for (i = split.length-1; i >= 0; i--) {
292 if (keyProps.containsKey(split[i])) {
298 result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
305 public ModelType getModelType() {
306 return ModelType.POJO;
310 public String getChildName() {
311 String className = internalObject.getClass().getSimpleName();
312 String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
314 if (this.isContainer()) {
315 lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().iterator().next()).getSimpleName());
322 public Map<PropertyMetadata, String> getPropertyMetadata(String prop) {
324 Map<PropertyMetadata, String> result = new HashMap<>();
326 f = internalObject.getClass().getField(prop);
327 Metadata m = f.getAnnotation(Metadata.class);
329 Field[] fields = m.getClass().getFields();
331 for (Field field : fields) {
332 fieldName = field.getName();
333 if (fieldName.equals("isAbstract")) {
334 fieldName = "abstract";
335 } else if (fieldName.equals("extendsFrom")) {
336 fieldName = "extends";
338 fieldName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, fieldName);
339 result.put(PropertyMetadata.valueOf(fieldName), (String)field.get(m));
342 } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
343 LOGGER2.error(e.getMessage(),e);
350 public String getObjectId() {
351 // TODO Auto-generated method stub
356 public String getMetadata(ObjectMetadata metadataName) {
359 if (ObjectMetadata.ABSTRACT.equals(metadataName)) {
360 methodName = "isAbstract";
361 } else if (ObjectMetadata.EXTENDS.equals(metadataName)) {
362 methodName = "extendsFrom";
364 methodName = metadataName.toString();
368 value = (String)this.classLevelMetadata.getClass().getMethod(methodName).invoke(classLevelMetadata);
369 } catch (IllegalArgumentException | IllegalAccessException | SecurityException | InvocationTargetException | NoSuchMethodException e) {
370 LOGGER2.error(e.getMessage(),e);
377 public Version getVersion() {
378 // TODO Auto-generated method stub