Update to use Schema Service
[aai/gizmo.git] / src / main / java / org / onap / schema / OxmModelLoader.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.schema;
22
23 import com.google.common.base.CaseFormat;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32 import javax.annotation.PostConstruct;
33 import javax.ws.rs.core.Response.Status;
34 import org.eclipse.persistence.dynamic.DynamicType;
35 import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
36 import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
37 import org.onap.aai.cl.eelf.LoggerFactory;
38 import org.onap.aai.nodes.NodeIngestor;
39 import org.onap.aai.setup.SchemaVersion;
40 import org.onap.aai.setup.Translator;
41 import org.onap.crud.exception.CrudException;
42 import org.onap.crud.logging.CrudServiceMsgs;
43 import org.springframework.beans.factory.annotation.Autowired;
44 import org.springframework.stereotype.Component;
45
46 @Component
47 public class OxmModelLoader {
48
49     private static Translator translator;
50     private static NodeIngestor nodeIngestor;
51
52     private static Map<String, DynamicJAXBContext> versionContextMap = new ConcurrentHashMap<>();
53     private static Map<String, HashMap<String, DynamicType>> xmlElementLookup = new ConcurrentHashMap<>();
54
55     final static Pattern versionPattern = Pattern.compile("(?i)v(\\d*)");
56
57     private static org.onap.aai.cl.api.Logger logger =
58             LoggerFactory.getInstance().getLogger(OxmModelLoader.class.getName());
59
60     private OxmModelLoader() { }
61
62     @Autowired
63     public OxmModelLoader(Translator translator, NodeIngestor nodeIngestor) {
64         OxmModelLoader.translator = translator;
65         OxmModelLoader.nodeIngestor = nodeIngestor;
66     }
67
68     @PostConstruct
69     public void init() throws CrudException {
70         OxmModelLoader.loadModels();
71     }
72
73     /**
74      * Finds all OXM model files
75      *
76      * @throws SpikeException
77      * @throws IOException
78      *
79      */
80     public synchronized static void loadModels() throws CrudException {
81
82         if (logger.isDebugEnabled()) {
83             logger.debug("Loading OXM Models");
84         }
85
86         for (SchemaVersion oxmVersion : translator.getSchemaVersions().getVersions()) {
87             DynamicJAXBContext jaxbContext = nodeIngestor.getContextForVersion(oxmVersion);
88             if (jaxbContext != null) {
89                 loadModel(oxmVersion.toString(), jaxbContext);
90             }
91         }
92     }
93
94
95     private synchronized static void loadModel(String oxmVersion, DynamicJAXBContext jaxbContext) {
96         versionContextMap.put(oxmVersion, jaxbContext);
97         loadXmlLookupMap(oxmVersion, jaxbContext);
98         logger.info(CrudServiceMsgs.LOADED_OXM_FILE, oxmVersion);
99     }
100
101     /**
102      * Retrieves the JAXB context for the specified OXM model version.
103      *
104      * @param version - The OXM version that we want the JAXB context for.
105      *
106      * @return - A JAXB context derived from the OXM model schema.
107      *
108      * @throws SpikeException
109      */
110     public static DynamicJAXBContext getContextForVersion(String version) throws CrudException {
111
112         // If we haven't already loaded in the available OXM models, then do so now.
113         if (versionContextMap == null || versionContextMap.isEmpty()) {
114             loadModels();
115         } else if (!versionContextMap.containsKey(version)) {
116             logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "Error loading oxm model: " + version);
117             throw new CrudException("Error loading oxm model: " + version, Status.INTERNAL_SERVER_ERROR);
118         }
119
120         return versionContextMap.get(version);
121     }
122
123     public static String getLatestVersion() throws CrudException {
124
125         // If we haven't already loaded in the available OXM models, then do so now.
126         if (versionContextMap == null || versionContextMap.isEmpty()) {
127             loadModels();
128         }
129
130         // If there are still no models available, then there's not much we can do...
131         if (versionContextMap.isEmpty()) {
132                         logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "No available OXM schemas to get latest version for.");
133             throw new CrudException("No available OXM schemas to get latest version for.", Status.INTERNAL_SERVER_ERROR);
134         }
135
136         // Iterate over the available model versions to determine which is the most
137         // recent.
138         Integer latestVersion = null;
139         String latestVersionStr = null;
140         for (String versionKey : versionContextMap.keySet()) {
141
142             Matcher matcher = versionPattern.matcher(versionKey);
143             if (matcher.find()) {
144
145                 int currentVersion = Integer.valueOf(matcher.group(1));
146
147                 if ((latestVersion == null) || (currentVersion > latestVersion)) {
148                     latestVersion = currentVersion;
149                     latestVersionStr = versionKey;
150                 }
151             }
152         }
153
154         return latestVersionStr;
155     }
156
157     /**
158      * Retrieves the map of all JAXB context objects that have been created by importing the
159      * available OXM model schemas.
160      *
161      * @return - Map of JAXB context objects.
162      */
163     public static Map<String, DynamicJAXBContext> getVersionContextMap() {
164         return versionContextMap;
165     }
166
167     /**
168      * Assigns the map of all JAXB context objects.
169      *
170      * @param versionContextMap
171      */
172     public static void setVersionContextMap(Map<String, DynamicJAXBContext> versionContextMap) {
173         OxmModelLoader.versionContextMap = versionContextMap;
174     }
175
176
177     public static void loadXmlLookupMap(String version, DynamicJAXBContext jaxbContext )  {
178
179         @SuppressWarnings("rawtypes")
180         List<Descriptor> descriptorsList = jaxbContext.getXMLContext().getDescriptors();
181         HashMap<String, DynamicType> types = new HashMap<String, DynamicType>();
182
183         for (@SuppressWarnings("rawtypes")
184         Descriptor desc : descriptorsList) {
185
186             DynamicType entity = jaxbContext.getDynamicType(desc.getAlias());
187             String entityName = desc.getDefaultRootElement();
188             types.put(entityName, entity);
189         }
190         xmlElementLookup.put(version, types);
191     }
192
193
194   public static DynamicType getDynamicTypeForVersion(String version, String type) throws CrudException {
195
196       DynamicType dynamicType;
197       // If we haven't already loaded in the available OXM models, then do so now.
198       if (versionContextMap == null || versionContextMap.isEmpty()) {
199           loadModels();
200       } else if (!versionContextMap.containsKey(version)) {
201           logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "Error loading oxm model: " + version);
202           throw new CrudException("Error loading oxm model: " + version, Status.INTERNAL_SERVER_ERROR);
203       }
204
205       // First try to match the Java-type based on hyphen to camel case
206       // translation
207       String javaTypeName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type);
208       dynamicType = versionContextMap.get(version).getDynamicType(javaTypeName);
209
210       if (xmlElementLookup.containsKey(version)) {
211           if (dynamicType == null) {
212               // Try to lookup by xml root element by exact match
213               dynamicType = xmlElementLookup.get(version).get(type);
214           }
215
216           if (dynamicType == null) {
217               // Try to lookup by xml root element by lowercase
218               dynamicType = xmlElementLookup.get(version).get(type.toLowerCase());
219           }
220
221           if (dynamicType == null) {
222               // Direct lookup as java-type name
223               dynamicType = versionContextMap.get(version).getDynamicType(type);
224           }
225       }
226
227       return dynamicType;
228   }
229
230   /**
231    * Retrieves the list of all Loaded OXM versions.
232    *
233    * @return - A List of Strings of all loaded OXM versions.
234    *
235    * @throws CrudException
236    */
237   public static List<String> getLoadedOXMVersions() throws CrudException {
238
239       // If we haven't already loaded in the available OXM models, then do so now.
240       if (versionContextMap == null || versionContextMap.isEmpty()) {
241           loadModels();
242       }
243
244       // If there are still no models available, then there's not much we can do...
245       if (versionContextMap.isEmpty()) {
246           logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "No available OXM schemas to get versions for.");
247           throw new CrudException("No available OXM schemas to get versions for.", Status.INTERNAL_SERVER_ERROR);
248       }
249
250       List<String> versions = new ArrayList<String>();
251       for (String versionKey : versionContextMap.keySet()) {
252
253           Matcher matcher = versionPattern.matcher(versionKey);
254           if (matcher.find()) {
255               versions.add ("V"+ matcher.group(1));
256           }
257       }
258       return versions;
259   }
260 }