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() {