2 * ============LICENSE_START=======================================================
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
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.onap.aai.introspection;
23 import com.att.eelf.configuration.EELFLogger;
24 import com.att.eelf.configuration.EELFManager;
25 import com.google.common.base.CaseFormat;
26 import com.google.common.base.Joiner;
28 import java.io.StringWriter;
29 import java.io.UnsupportedEncodingException;
31 import java.util.Map.Entry;
33 import javax.xml.bind.JAXBException;
34 import javax.xml.bind.Marshaller;
36 import org.eclipse.persistence.descriptors.ClassDescriptor;
37 import org.eclipse.persistence.dynamic.DynamicEntity;
38 import org.eclipse.persistence.dynamic.DynamicType;
39 import org.eclipse.persistence.exceptions.DynamicException;
40 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
41 import org.eclipse.persistence.mappings.DatabaseMapping;
42 import org.eclipse.persistence.oxm.XMLField;
43 import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
44 import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping;
45 import org.onap.aai.config.SpringContextAware;
46 import org.onap.aai.logging.LogFormatTools;
47 import org.onap.aai.nodes.CaseFormatStore;
48 import org.onap.aai.nodes.NodeIngestor;
49 import org.onap.aai.restcore.MediaType;
50 import org.onap.aai.schema.enums.ObjectMetadata;
51 import org.onap.aai.schema.enums.PropertyMetadata;
52 import org.onap.aai.setup.SchemaVersion;
53 import org.springframework.web.util.UriUtils;
55 public class MoxyStrategy extends Introspector {
57 private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(MoxyStrategy.class);
58 private DynamicEntity internalObject = null;
59 private DynamicType internalType = null;
60 private DynamicJAXBContext jaxbContext = null;
61 private ClassDescriptor cd = null;
62 private SchemaVersion version = null;
63 private Set<String> properties = null;
64 private Set<String> keys = null;
65 private Set<String> requiredProperties = null;
67 private boolean isInitialized = false;
69 protected MoxyStrategy(Object obj) {
71 /* must look up the correct jaxbcontext for this object */
72 className = MoxyStrategy.class.getSimpleName();
73 internalObject = (DynamicEntity) obj;
74 version = nodeIngestor.getVersionFromClassName(internalObject.getClass().getName());
75 super.loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(getModelType(), version);
76 jaxbContext = nodeIngestor.getContextForVersion(version);
77 String simpleName = internalObject.getClass().getName();
78 internalType = jaxbContext.getDynamicType(simpleName);
80 cd = internalType.getDescriptor();
86 Set<String> props = new LinkedHashSet<>();
87 for (String s : internalType.getPropertiesNames()) {
88 String value = caseFormatStore.fromLowerCamelToLowerHyphen(s).orElseGet(() -> {
89 LOGGER.debug("Unable to find {} in the store from lower camel to lower hyphen", s);
90 return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, s);
95 props = Collections.unmodifiableSet(props);
96 this.properties = props;
98 Set<String> requiredProps = new LinkedHashSet<>();
99 for (DatabaseMapping dm : cd.getMappings()) {
100 if (dm.getField() instanceof XMLField) {
101 XMLField x = (XMLField) dm.getField();
102 if (x != null && x.isRequired()) {
103 requiredProps.add(this.removeXPathDescriptor(x.getName()));
107 requiredProps = Collections.unmodifiableSet(requiredProps);
108 this.requiredProperties = requiredProps;
110 Set<String> keys = new LinkedHashSet<>();
112 for (String name : internalType.getDescriptor().getPrimaryKeyFieldNames()) {
113 keys.add(this.removeXPathDescriptor(name));
115 keys = Collections.unmodifiableSet(keys);
121 public boolean hasProperty(String name) {
122 String convertedName = convertPropertyName(name);
124 return internalType.containsProperty(convertedName);
128 public Object get(String name) {
129 return internalObject.get(name);
133 public void set(String name, Object obj) {
135 internalObject.set(name, obj);
139 public Set<String> getProperties() {
141 if (!isInitialized) {
145 return this.properties;
150 public Set<String> getRequiredProperties() {
152 if (!isInitialized) {
156 return this.requiredProperties;
160 public Set<String> getKeys() {
162 if (!isInitialized) {
170 public Map<PropertyMetadata, String> getPropertyMetadata(String prop) {
171 String propName = this.convertPropertyName(prop);
172 DatabaseMapping mapping = cd.getMappingForAttributeName(propName);
173 Map<PropertyMetadata, String> result = new HashMap<>();
174 if (mapping != null) {
175 Set<Entry> entrySet = mapping.getProperties().entrySet();
176 for (Entry<?, ?> entry : entrySet) {
178 PropertyMetadata.valueOf(
179 CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, (String) entry.getKey())),
180 (String) entry.getValue());
188 public String getJavaClassName() {
189 return internalObject.getClass().getName();
193 public Class<?> getClass(String name) {
194 name = convertPropertyName(name);
195 Class<?> resultClass = null;
197 if (internalType.getPropertyType(name) == null) {
198 if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
199 resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
201 } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
202 resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
204 ClassDescriptor referenceDiscriptor = cd.getMappingForAttributeName(name).getReferenceDescriptor();
205 if (referenceDiscriptor != null) {
206 resultClass = referenceDiscriptor.getJavaClass();
208 resultClass = Object.class;
212 resultClass = internalType.getPropertyType(name);
214 } catch (DynamicException e) {
215 // property doesn't exist
221 public Class<?> getGenericTypeClass(String name) {
222 name = convertPropertyName(name);
223 Class<?> resultClass = null;
224 if (internalType.getPropertyType(name) == null) {
225 if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
226 resultClass = cd.getMappingForAttributeName(name).getFields().get(0).getType();
228 } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
229 resultClass = cd.getMappingForAttributeName(name).getReferenceDescriptor().getJavaClass();
237 public Object getUnderlyingObject() {
238 return this.internalObject;
242 public String getChildName() {
244 String className = internalObject.getClass().getSimpleName();
245 String lowerHyphen = caseFormatStore.fromUpperCamelToLowerHyphen(className).orElseGet(() -> {
246 LOGGER.debug("Unable to find {} in the store for upper camel to lower hyphen", className);
247 return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
250 if (this.isContainer()) {
251 String upperCamel = this.getGenericTypeClass(this.getProperties().iterator().next()).getSimpleName();
253 lowerHyphen = caseFormatStore.fromUpperCamelToLowerHyphen(upperCamel).orElseGet(() -> {
254 LOGGER.debug("Unable to find {} in the store for upper camel to lower hyphen", upperCamel);
255 return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, upperCamel);
263 public String getName() {
264 String className = internalObject.getClass().getSimpleName();
265 return caseFormatStore.fromUpperCamelToLowerHyphen(className).orElseGet(() -> {
266 LOGGER.debug("Unable to find {} in the store for upper camel to lower hyphen", className);
267 return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
272 public String getObjectId() throws UnsupportedEncodingException {
274 String container = this.getMetadata(ObjectMetadata.CONTAINER);
275 if (this.isContainer()) {
276 result += "/" + this.getName();
279 if (container != null) {
280 result += "/" + container;
282 result += "/" + this.getDbName() + "/" + this.findKey();
290 protected String findKey() throws UnsupportedEncodingException {
291 Set<String> keys = null;
292 keys = this.getKeys();
293 List<String> results = new ArrayList<>();
294 for (String key : keys) {
295 String value = UriUtils.encode(this.getValue(key).toString(), "UTF-8");
299 return Joiner.on("/").join(results);
303 public String preProcessKey(String key) {
305 String[] split = key.split("/");
307 for (i = split.length - 1; i >= 0; i--) {
309 if (jaxbContext.getDynamicType(split[i]) != null) {
315 result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
322 public String marshal(MarshallerProperties properties) {
323 StringWriter result = new StringWriter();
325 Marshaller marshaller = jaxbContext.createMarshaller();
326 if (properties.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)) {
327 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE,
329 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT,
330 properties.getIncludeRoot());
331 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME,
332 properties.getWrapperAsArrayName());
333 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS,
337 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
338 marshaller.marshal(this.internalObject, result);
339 } catch (JAXBException e) {
340 LOGGER.warn("Encountered an jaxb exception during marshalling ", LogFormatTools.getStackTop(e));
343 return result.toString();
347 public ModelType getModelType() {
348 return ModelType.MOXY;
351 private String removeXPathDescriptor(String name) {
353 return name.replaceAll("/text\\(\\)", "");
357 public String getMetadata(ObjectMetadata name) {
359 return (String) cd.getProperty(name.toString());
363 public SchemaVersion getVersion() {