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 org.eclipse.persistence.descriptors.ClassDescriptor;
29 import org.eclipse.persistence.dynamic.DynamicEntity;
30 import org.eclipse.persistence.dynamic.DynamicType;
31 import org.eclipse.persistence.exceptions.DynamicException;
32 import org.eclipse.persistence.jaxb.UnmarshallerProperties;
33 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
34 import org.eclipse.persistence.mappings.DatabaseMapping;
35 import org.eclipse.persistence.oxm.XMLField;
36 import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
37 import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping;
38 import org.onap.aai.restcore.MediaType;
39 import org.onap.aai.schema.enums.ObjectMetadata;
40 import org.onap.aai.schema.enums.PropertyMetadata;
41 import org.springframework.web.util.UriUtils;
43 import javax.xml.bind.JAXBException;
44 import javax.xml.bind.Marshaller;
45 import javax.xml.bind.Unmarshaller;
46 import javax.xml.transform.stream.StreamSource;
47 import java.io.StringReader;
48 import java.io.StringWriter;
49 import java.io.UnsupportedEncodingException;
51 import java.util.Map.Entry;
53 public class MoxyStrategy extends Introspector {
55 private static final EELFLogger LOGGER2 = EELFManager.getInstance().getLogger(MoxyStrategy.class);
57 private DynamicEntity internalObject = null;
58 private DynamicType internalType = null;
59 private DynamicJAXBContext jaxbContext = null;
60 private ClassDescriptor cd = null;
61 private Marshaller marshaller = null;
62 private Unmarshaller unmarshaller = null;
63 private Version version = null;
64 private Set<String> properties = null;
65 private Set<String> keys = null;
66 private Set<String> requiredProperties = null;
68 private boolean isInitialized = false;
70 protected MoxyStrategy(Object obj) {
72 /* must look up the correct jaxbcontext for this object */
73 className = MoxyStrategy.class.getSimpleName();
74 internalObject = (DynamicEntity)obj;
75 ModelInjestor injestor = ModelInjestor.getInstance();
76 version = injestor.getVersionFromClassName(internalObject.getClass().getName());
77 jaxbContext = injestor.getContextForVersion(version);
78 super.loader = LoaderFactory.createLoaderForVersion(getModelType(), version);
79 String simpleName = internalObject.getClass().getName();
80 internalType = jaxbContext.getDynamicType(simpleName);
81 cd = internalType.getDescriptor();
83 marshaller = jaxbContext.createMarshaller();
84 unmarshaller = jaxbContext.createUnmarshaller();
85 } catch (JAXBException e) {
86 LOGGER2.error(e.getMessage(),e);
94 Set<String> props = new LinkedHashSet<>();
95 for (String s : internalType.getPropertiesNames()) {
96 props.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, s));
99 props = Collections.unmodifiableSet(props);
100 this.properties = props;
102 Set<String> requiredProps = new LinkedHashSet<>();
103 requiredProps = new LinkedHashSet<>();
104 for (DatabaseMapping dm : cd.getMappings()) {
105 if (dm.getField() instanceof XMLField) {
106 XMLField x = (XMLField)dm.getField();
108 if (x.isRequired()) {
109 requiredProps.add(this.removeXPathDescriptor(x.getName()));
114 requiredProps = Collections.unmodifiableSet(requiredProps);
115 this.requiredProperties = requiredProps;
117 Set<String> keys = new LinkedHashSet<>();
119 for (String name : internalType.getDescriptor().getPrimaryKeyFieldNames()) {
120 keys.add(this.removeXPathDescriptor(name));
122 keys = Collections.unmodifiableSet(keys);
129 public boolean hasProperty(String name) {
130 String convertedName = convertPropertyName(name);
132 return internalType.containsProperty(convertedName);
136 public Object get(String name) {
137 return internalObject.get(name);
141 public void set(String name, Object obj) throws IllegalArgumentException {
143 internalObject.set(name, obj);
147 public Set<String> getProperties() {
153 return this.properties;
158 public Set<String> getRequiredProperties() {
164 return this.requiredProperties;
168 public Set<String> getKeys() {
178 public Map<PropertyMetadata, String> getPropertyMetadata(String prop) {
179 String propName = this.convertPropertyName(prop);
180 DatabaseMapping mapping = cd.getMappingForAttributeName(propName);
181 Map<PropertyMetadata, String> result = new HashMap<>();
182 if (mapping != null) {
183 Set<Entry> entrySet = mapping.getProperties().entrySet();
184 for (Entry<?,?> entry : entrySet) {
186 PropertyMetadata.valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, (String)entry.getKey())), (String)entry.getValue());
194 public String getJavaClassName() {
195 return internalObject.getClass().getName();
201 public Class<?> getClass(String name) {
202 name = convertPropertyName(name);
203 Class<?> resultClass = null;
205 if (internalType.getPropertyType(name) == null) {
206 if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
207 resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
209 } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
210 resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
212 ClassDescriptor referenceDiscriptor = cd.getMappingForAttributeName(name).getReferenceDescriptor();
213 if (referenceDiscriptor != null) {
214 resultClass = referenceDiscriptor.getJavaClass();
216 resultClass = Object.class;
220 resultClass = internalType.getPropertyType(name);
222 } catch (DynamicException e) {
223 //property doesn't exist
224 LOGGER2.error(e.getMessage(),e);
230 public Class<?> getGenericTypeClass(String name) {
231 name = convertPropertyName(name);
232 Class<?> resultClass = null;
233 if (internalType.getPropertyType(name) == null) {
234 if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
235 resultClass = cd.getMappingForAttributeName(name).getFields().get(0).getType();
237 } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
238 resultClass = cd.getMappingForAttributeName(name).getReferenceDescriptor().getJavaClass();
246 public Object getUnderlyingObject() {
247 return this.internalObject;
251 public String getChildName() {
253 String className = internalObject.getClass().getSimpleName();
254 String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
256 if (this.isContainer()) {
257 lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().iterator().next()).getSimpleName());
264 public String getName() {
265 String className = internalObject.getClass().getSimpleName();
266 String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
268 if (this.isContainer()) {
269 lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().get(0)).getSimpleName());
277 public String getObjectId() throws UnsupportedEncodingException {
279 String container = this.getMetadata(ObjectMetadata.CONTAINER);
280 if (this.isContainer()) {
281 result += "/" + this.getName();
284 if (container != null) {
285 result += "/" + container;
287 result += "/" + this.getDbName() + "/" + this.findKey();
295 protected String findKey() throws UnsupportedEncodingException {
296 Set<String> keys = null;
297 keys = this.getKeys();
298 List<String> results = new ArrayList<>();
299 for (String key : keys) {
300 String value = UriUtils.encode(this.getValue(key).toString(), "UTF-8");
304 return Joiner.on("/").join(results);
308 public String preProcessKey (String key) {
310 //String trimmedRestURI = restURI.replaceAll("/[\\w\\-]+?/[\\w\\-]+?$", "");
311 String[] split = key.split("/");
313 for (i = split.length-1; i >= 0; i--) {
315 if (jaxbContext.getDynamicType(split[i]) != null) {
321 result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
328 public String marshal(MarshallerProperties properties) {
329 StringWriter result = new StringWriter();
331 if (properties.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)) {
332 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE, "application/json");
333 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT, properties.getIncludeRoot());
334 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, properties.getWrapperAsArrayName());
335 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, false);
337 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
338 marshaller.marshal(this.internalObject, result);
339 } catch (JAXBException e) {
340 LOGGER2.error(e.getMessage(),e);
343 return result.toString();
347 public Object clone() {
348 Object result = null;
350 unmarshaller = jaxbContext.createUnmarshaller();
352 unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
353 unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
354 unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
356 result = unmarshaller.unmarshal(new StreamSource(new StringReader(this.marshal(true))), this.internalObject.getClass()).getValue();
357 } catch (JAXBException e) {
358 LOGGER2.error(e.getMessage(),e);
360 result = IntrospectorFactory.newInstance(getModelType(), result);
364 public ModelType getModelType() {
365 return ModelType.MOXY;
368 private String removeXPathDescriptor(String name) {
370 return name.replaceAll("/text\\(\\)", "");
374 public String getMetadata(ObjectMetadata name) {
376 return (String)cd.getProperty(name.toString());
380 public Version getVersion() {