Optimize the areas where its creating extra memory
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / introspection / MoxyLoader.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
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
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20 package org.onap.aai.introspection;
21
22 import com.att.eelf.configuration.EELFLogger;
23 import com.att.eelf.configuration.EELFManager;
24 import com.google.common.base.CaseFormat;
25 import com.google.common.collect.ImmutableMap;
26
27 import org.eclipse.persistence.dynamic.DynamicEntity;
28 import org.eclipse.persistence.jaxb.UnmarshallerProperties;
29 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
30 import org.onap.aai.exceptions.AAIException;
31 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
32 import org.onap.aai.introspection.exceptions.AAIUnmarshallingException;
33 import org.onap.aai.logging.ErrorLogHelper;
34 import org.onap.aai.logging.LogFormatTools;
35 import org.onap.aai.nodes.CaseFormatStore;
36 import org.onap.aai.nodes.NodeIngestor;
37 import org.onap.aai.restcore.MediaType;
38 import org.onap.aai.schema.enums.ObjectMetadata;
39 import org.onap.aai.setup.SchemaVersion;
40 import org.onap.aai.workarounds.NamingExceptions;
41 import javax.xml.bind.JAXBException;
42 import javax.xml.bind.Unmarshaller;
43 import javax.xml.transform.stream.StreamSource;
44 import java.io.*;
45 import java.util.HashSet;
46 import java.util.Map;
47 import java.util.Set;
48 import java.util.stream.Collectors;
49
50 public class MoxyLoader extends Loader {
51
52     private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(MoxyLoader.class);
53
54         private DynamicJAXBContext jaxbContext = null;
55         private Map<String, Introspector> allObjs = null;
56
57         private Map<SchemaVersion, MoxyLoader> moxyLoaderFactory;
58
59         private NodeIngestor nodeIngestor;
60         private CaseFormatStore caseFormatStore;
61
62         private Set<String> namedProps;
63
64         public MoxyLoader(SchemaVersion version, NodeIngestor nodeIngestor) {
65                 super(version, ModelType.MOXY);
66                 this.nodeIngestor = nodeIngestor;
67                 this.caseFormatStore = nodeIngestor.getCaseFormatStore();
68                 process(version);
69         }
70
71         public MoxyLoader getMoxyLoader(SchemaVersion v) {
72                 return moxyLoaderFactory.get(v);
73
74         }
75         /**
76          * {@inheritDoc}
77          * @throws AAIUnknownObjectException
78          */
79         @Override
80         public Introspector introspectorFromName(String name) throws AAIUnknownObjectException {
81
82                 return IntrospectorFactory.newInstance(ModelType.MOXY, objectFromName(name));
83         }
84
85         private boolean containsUpperCase(String str){
86
87             for(int i = 0; i < str.length(); i++){
88                 if(Character.isUpperCase(str.charAt(i))){
89                     return true;
90             }
91         }
92
93         return false;
94     }
95         /**
96          * {@inheritDoc}
97          */
98         @Override
99         public Object objectFromName(String name) throws AAIUnknownObjectException {
100
101                 if (name == null) {
102                         throw new AAIUnknownObjectException("null name passed in");
103                 }
104                 final String sanitizedName = NamingExceptions.getInstance().getObjectName(name);
105                 final String upperCamel;
106
107                 //Contains any uppercase, then assume it's upper camel
108                 if (containsUpperCase(name)) {
109                         upperCamel = sanitizedName;
110                 } else {
111                         upperCamel = caseFormatStore
112                 .fromLowerHyphenToUpperCamel(sanitizedName)
113                 .orElseGet(
114                     () -> {
115                         LOGGER.debug("Unable to find {} in the store for lower hyphen to upper camel", sanitizedName);
116                         return CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, sanitizedName);
117                     }
118                 );
119                 }
120
121                 try {
122                         final DynamicEntity result = jaxbContext.newDynamicEntity(upperCamel);
123
124                         if (result == null) throw new AAIUnknownObjectException("Unrecognized AAI object " + name);
125
126                         return result;
127                 } catch (IllegalArgumentException e) {
128                         //entity does not exist
129                         throw new AAIUnknownObjectException("Unrecognized AAI object " + name, e);
130                 }
131         }
132
133         /**
134          * {@inheritDoc}
135          */
136         @Override
137         protected void process(SchemaVersion version) {
138                 /*
139                  * We need to have just same JaxbContext for each version
140                  */
141                 jaxbContext = nodeIngestor.getContextForVersion(version);
142
143         }
144
145         /**
146          * {@inheritDoc}
147          */
148         @Override
149         public Introspector unmarshal(String type, String json, MediaType mediaType) throws AAIUnmarshallingException {
150                 try {
151                         final Object clazz = objectFromName(type);
152                         final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
153
154                         if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
155                                 unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
156                                 unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
157                                 unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
158                         }
159
160                         final DynamicEntity entity = (DynamicEntity) unmarshaller.unmarshal(new StreamSource(new StringReader(json)), clazz.getClass()).getValue();
161                         return IntrospectorFactory.newInstance(ModelType.MOXY, entity);
162                 } catch (JAXBException e) {
163                         AAIException ex = new AAIException("AAI_4007", e);
164                         ErrorLogHelper.logException(ex);
165                         throw new AAIUnmarshallingException("Could not unmarshall: " + e.getMessage(), ex);
166                 } catch (AAIUnknownObjectException e) {
167                         throw new AAIUnmarshallingException("Could not unmarshall: " + e.getMessage(), e);
168                 }
169         }
170
171         @Override
172         public Map<String, Introspector> getAllObjects() {
173                 if (this.allObjs != null) {
174                         return allObjs;
175                 } else {
176                         ImmutableMap.Builder<String, Introspector> map = new ImmutableMap.Builder<>();
177                         Set<String> objs = objectsInVersion();
178                         for (String objName : objs) {
179                                 try {
180                                         Introspector introspector = this.introspectorFromName(objName);
181                                         map.put(introspector.getDbName(), introspector);
182                                 } catch (AAIUnknownObjectException e) {
183                                         LOGGER.warn("Unexpected AAIUnknownObjectException while running getAllObjects() " + LogFormatTools.getStackTop(e));
184                                 }
185                         }
186                         allObjs = map.build();
187                         return allObjs;
188                 }
189         }
190
191         private Set<String> objectsInVersion() {
192                  Set<String> result = new HashSet<>();
193
194                 try {
195                  result = nodeIngestor.getObjectsInVersion(getVersion());
196
197                 } catch (Exception e) {
198                         LOGGER.warn("Exception while enumerating objects for API version " + getVersion() + " (returning partial results) " + LogFormatTools.getStackTop(e));
199                 }
200
201                 return result;
202         }
203
204         @Override
205         public Set<String> getNamedPropNodes(){
206
207         if(namedProps == null){
208                 namedProps = getAllObjects()
209                 .entrySet()
210                 .stream()
211                 .filter(
212                     (entry) -> entry.getValue().getMetadata(ObjectMetadata.NAME_PROPS) != null
213                 ).map(entry -> entry.getKey()).collect(Collectors.toSet());
214         }
215
216         return namedProps;
217     }
218         public DynamicJAXBContext getJAXBContext() {
219                 return this.jaxbContext;
220         }
221 }