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.io.UnsupportedEncodingException;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.LinkedHashSet;
31 import java.util.List;
33 import java.util.Map.Entry;
36 import javax.xml.bind.JAXBException;
37 import javax.xml.bind.Marshaller;
38 import javax.xml.bind.Unmarshaller;
39 import javax.xml.transform.stream.StreamSource;
41 import org.eclipse.persistence.descriptors.ClassDescriptor;
42 import org.eclipse.persistence.dynamic.DynamicEntity;
43 import org.eclipse.persistence.dynamic.DynamicType;
44 import org.eclipse.persistence.exceptions.DynamicException;
45 import org.eclipse.persistence.jaxb.UnmarshallerProperties;
46 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
47 import org.eclipse.persistence.mappings.DatabaseMapping;
48 import org.eclipse.persistence.oxm.XMLField;
49 import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
50 import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping;
51 import org.springframework.web.util.UriUtils;
53 import org.openecomp.aai.restcore.MediaType;
54 import org.openecomp.aai.schema.enums.ObjectMetadata;
55 import org.openecomp.aai.schema.enums.PropertyMetadata;
56 import com.google.common.base.CaseFormat;
57 import com.google.common.base.Joiner;
59 public class MoxyStrategy extends Introspector {
61 private DynamicEntity internalObject = null;
62 private DynamicType internalType = null;
63 private DynamicJAXBContext jaxbContext = null;
64 private ClassDescriptor cd = null;
65 private Marshaller marshaller = null;
66 private Unmarshaller unmarshaller = null;
67 private Version version = null;
68 private Set<String> properties = null;
69 private Set<String> keys = null;
70 private Set<String> requiredProperties = null;
72 private boolean isInitialized = false;
74 protected MoxyStrategy(Object obj) {
76 /* must look up the correct jaxbcontext for this object */
77 className = MoxyStrategy.class.getSimpleName();
78 internalObject = (DynamicEntity)obj;
79 ModelInjestor injestor = ModelInjestor.getInstance();
80 version = injestor.getVersionFromClassName(internalObject.getClass().getName());
81 jaxbContext = injestor.getContextForVersion(version);
82 super.loader = LoaderFactory.createLoaderForVersion(getModelType(), version);
83 String simpleName = internalObject.getClass().getName();
84 internalType = jaxbContext.getDynamicType(simpleName);
85 cd = internalType.getDescriptor();
87 marshaller = jaxbContext.createMarshaller();
88 unmarshaller = jaxbContext.createUnmarshaller();
89 } catch (JAXBException e) {
98 Set<String> props = new LinkedHashSet<>();
99 for (String s : internalType.getPropertiesNames()) {
100 props.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, s));
103 props = Collections.unmodifiableSet(props);
104 this.properties = props;
106 Set<String> requiredProps = new LinkedHashSet<>();
107 requiredProps = new LinkedHashSet<>();
108 for (DatabaseMapping dm : cd.getMappings()) {
109 if (dm.getField() instanceof XMLField) {
110 XMLField x = (XMLField)dm.getField();
112 if (x.isRequired()) {
113 requiredProps.add(this.removeXPathDescriptor(x.getName()));
118 requiredProps = Collections.unmodifiableSet(requiredProps);
119 this.requiredProperties = requiredProps;
121 Set<String> keys = new LinkedHashSet<>();
123 for (String name : internalType.getDescriptor().getPrimaryKeyFieldNames()) {
124 keys.add(this.removeXPathDescriptor(name));
126 keys = Collections.unmodifiableSet(keys);
133 public boolean hasProperty(String name) {
134 String convertedName = convertPropertyName(name);
136 return internalType.containsProperty(convertedName);
140 public Object get(String name) {
141 return internalObject.get(name);
145 public void set(String name, Object obj) throws IllegalArgumentException {
147 internalObject.set(name, obj);
151 public Set<String> getProperties() {
157 return this.properties;
162 public Set<String> getRequiredProperties() {
168 return this.requiredProperties;
172 public Set<String> getKeys() {
182 public Map<PropertyMetadata, String> getPropertyMetadata(String prop) {
183 String propName = this.convertPropertyName(prop);
184 DatabaseMapping mapping = cd.getMappingForAttributeName(propName);
185 Map<PropertyMetadata, String> result = new HashMap<>();
186 if (mapping != null) {
187 Set<Entry> entrySet = mapping.getProperties().entrySet();
188 for (Entry<?,?> entry : entrySet) {
190 PropertyMetadata.valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, (String)entry.getKey())), (String)entry.getValue());
198 public String getJavaClassName() {
199 return internalObject.getClass().getName();
205 public Class<?> getClass(String name) {
206 name = convertPropertyName(name);
207 Class<?> resultClass = null;
209 if (internalType.getPropertyType(name) == null) {
210 if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
211 resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
213 } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
214 resultClass = cd.getMappingForAttributeName(name).getContainerPolicy().getContainerClass();
216 ClassDescriptor referenceDiscriptor = cd.getMappingForAttributeName(name).getReferenceDescriptor();
217 if (referenceDiscriptor != null) {
218 resultClass = referenceDiscriptor.getJavaClass();
220 resultClass = Object.class;
224 resultClass = internalType.getPropertyType(name);
226 } catch (DynamicException e) {
227 //property doesn't exist
233 public Class<?> getGenericTypeClass(String name) {
234 name = convertPropertyName(name);
235 Class<?> resultClass = null;
236 if (internalType.getPropertyType(name) == null) {
237 if (cd.getMappingForAttributeName(name) instanceof XMLCompositeDirectCollectionMapping) {
238 resultClass = cd.getMappingForAttributeName(name).getFields().get(0).getType();
240 } else if (cd.getMappingForAttributeName(name) instanceof XMLCompositeCollectionMapping) {
241 resultClass = cd.getMappingForAttributeName(name).getReferenceDescriptor().getJavaClass();
249 public Object getUnderlyingObject() {
250 return this.internalObject;
254 public String getChildName() {
256 String className = internalObject.getClass().getSimpleName();
257 String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
259 if (this.isContainer()) {
260 lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().iterator().next()).getSimpleName());
267 public String getName() {
268 String className = internalObject.getClass().getSimpleName();
269 String lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, className);
271 if (this.isContainer()) {
272 lowerHyphen = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,this.getGenericTypeClass(this.getProperties().get(0)).getSimpleName());
280 public String getObjectId() throws UnsupportedEncodingException {
282 String container = this.getMetadata(ObjectMetadata.CONTAINER);
283 if (this.isContainer()) {
284 result += "/" + this.getName();
287 if (container != null) {
288 result += "/" + container;
290 result += "/" + this.getDbName() + "/" + this.findKey();
298 protected String findKey() throws UnsupportedEncodingException {
299 Set<String> keys = null;
300 keys = this.getKeys();
301 List<String> results = new ArrayList<>();
302 for (String key : keys) {
303 if (this.getType(key).toLowerCase().contains("long")) {
304 key = ((Long)this.getValue(key)).toString();
306 key = (String)this.getValue(key);
308 key = UriUtils.encode(key, "UTF-8");
313 return Joiner.on("/").join(results);
317 public String preProcessKey (String key) {
319 //String trimmedRestURI = restURI.replaceAll("/[\\w\\-]+?/[\\w\\-]+?$", "");
320 String[] split = key.split("/");
322 for (i = split.length-1; i >= 0; i--) {
324 if (jaxbContext.getDynamicType(split[i]) != null) {
330 result = Joiner.on("/").join(Arrays.copyOfRange(split, 0, i));
337 public String marshal(MarshallerProperties properties) {
338 StringWriter result = new StringWriter();
340 if (properties.getMediaType().equals(MediaType.APPLICATION_JSON_TYPE)) {
341 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE, "application/json");
342 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT, properties.getIncludeRoot());
343 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, properties.getWrapperAsArrayName());
344 marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, false);
346 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, properties.getFormatted());
347 marshaller.marshal(this.internalObject, result);
348 } catch (JAXBException e) {
349 //e.printStackTrace();
352 return result.toString();
356 public Object clone() {
357 Object result = null;
359 unmarshaller = jaxbContext.createUnmarshaller();
361 unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
362 unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
363 unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
365 result = unmarshaller.unmarshal(new StreamSource(new StringReader(this.marshal(true))), this.internalObject.getClass()).getValue();
366 } catch (JAXBException e) {
367 // TODO Auto-generated catch block
368 //e.printStackTrace();
370 result = IntrospectorFactory.newInstance(getModelType(), result);
374 public ModelType getModelType() {
375 return ModelType.MOXY;
378 private String removeXPathDescriptor(String name) {
380 return name.replaceAll("/text\\(\\)", "");
384 public String getMetadata(ObjectMetadata name) {
386 return (String)cd.getProperty(name.toString());
390 public Version getVersion() {