Merge "Release 1.14.0 maven artifact"
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / audit / ListEndpoints.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  *
7  * Modifications Copyright (C) 2019 IBM.
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *    http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.aai.audit;
24
25 import com.google.common.base.CaseFormat;
26
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.LinkedHashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36
37 import org.apache.commons.lang3.StringUtils;
38 import org.onap.aai.config.SpringContextAware;
39 import org.onap.aai.introspection.Introspector;
40 import org.onap.aai.introspection.Loader;
41 import org.onap.aai.introspection.LoaderFactory;
42 import org.onap.aai.introspection.ModelType;
43 import org.onap.aai.introspection.exceptions.AAIUnknownObjectException;
44 import org.onap.aai.logging.LogFormatTools;
45 import org.onap.aai.setup.SchemaVersion;
46 import org.onap.aai.setup.SchemaVersions;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.springframework.beans.BeansException;
50 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
51
52 /**
53  * The Class ListEndpoints.
54  */
55 public class ListEndpoints {
56
57     private static final Logger LOGGER = LoggerFactory.getLogger(ListEndpoints.class);
58
59     private static final String START = "inventory";
60     private static final String[] blacklist = {"search", "aai-internal"};
61
62     private List<String> endpoints = new ArrayList<>();
63     private Map<String, String> endpointToLogicalName = new HashMap<>();
64
65     /**
66      * The main method.
67      *
68      * @param args the arguments
69      */
70     public static void main(String[] args) {
71
72         try (AnnotationConfigApplicationContext context =
73                 new AnnotationConfigApplicationContext("org.onap.aai.config", "org.onap.aai.setup")) {
74             String schemaUriBasePath = context.getEnvironment().getProperty("schema.uri.base.path");
75
76             if (schemaUriBasePath == null) {
77                 String errorMsg = "Unable to find the property schema.uri.base.path,"
78                         + " please check if specified in system property or in schema-ingest.properties";
79                 LOGGER.error(errorMsg);
80             }
81
82             SchemaVersions schemaVersions = context.getBean(SchemaVersions.class);
83             ListEndpoints endPoints = new ListEndpoints(schemaUriBasePath, schemaVersions.getDefaultVersion());
84
85             LOGGER.info(endPoints.toString("relationship-list"));
86         } catch (BeansException e) {
87             LOGGER.warn("Unable to initialize AnnotationConfigApplicationContext ", LogFormatTools.getStackTop(e));
88         }
89     }
90
91     /**
92      * Instantiates a new list endpoints.
93      *
94      * @param version the version
95      */
96     public ListEndpoints(String basePath, SchemaVersion version) {
97
98         Loader loader = SpringContextAware.getBean(LoaderFactory.class).createLoaderForVersion(ModelType.MOXY, version);
99
100         try {
101             final Introspector start = loader.introspectorFromName(START);
102             Set<String> startMap = new HashSet<>();
103             beginAudit(start, basePath + "/" + version, startMap);
104         } catch (AAIUnknownObjectException e) {
105             throw new RuntimeException("Failed to find object " + START + ", cannot run ListEndpoints audit");
106         }
107     }
108
109     /**
110      * Begin audit.
111      *
112      * @param obj the obj
113      * @param uri the uri
114      */
115     private void beginAudit(Introspector obj, String uri, Set<String> visited) {
116
117         String currentUri = "";
118
119         if (!obj.getDbName().equals(START)) {
120             currentUri = uri + obj.getGenericURI();
121         } else {
122             currentUri = uri;
123         }
124         if (obj.getName().equals("relationship-data") || obj.getName().equals("related-to-property")) {
125             return;
126         }
127         if (!obj.isContainer()) {
128             endpoints.add(currentUri);
129         }
130
131         populateLogicalName(obj, uri, currentUri);
132
133         Set<String> properties = obj.getProperties();
134         Set<String> props = new LinkedHashSet<>(properties);
135         if (obj.isContainer()) {
136             for (String key : visited) {
137                 if (props.remove(key)) {
138                     try {
139                         endpoints.add(currentUri + obj.getLoader().introspectorFromName(key).getGenericURI());
140                     } catch (AAIUnknownObjectException e) {
141                         LOGGER.warn(
142                                 "Skipping endpoint for " + key + " (Unknown object) " + LogFormatTools.getStackTop(e));
143                     }
144                 }
145             }
146         }
147
148         outer: for (String propName : props) {
149
150             for (String item : blacklist) {
151                 if (propName.equals(item)) {
152                     continue outer;
153                 }
154             }
155             if (obj.isListType(propName)) {
156                 if (obj.isComplexGenericType(propName)) {
157                     try {
158                         final Introspector nestedObj = obj.newIntrospectorInstanceOfNestedProperty(propName);
159                         Set<String> newVisited = new HashSet<>();
160                         newVisited.addAll(visited);
161                         newVisited.add(nestedObj.getDbName());
162                         beginAudit(nestedObj, currentUri, newVisited);
163                     } catch (AAIUnknownObjectException e) {
164                         LOGGER.warn("Skipping nested endpoint for " + propName + " (Unknown Object) "
165                                 + LogFormatTools.getStackTop(e));
166                     }
167                 }
168             } else if (obj.isComplexType(propName)) {
169                 try {
170                     final Introspector nestedObj = obj.newIntrospectorInstanceOfProperty(propName);
171                     Set<String> newVisited = new HashSet<>();
172                     newVisited.addAll(visited);
173                     newVisited.add(nestedObj.getDbName());
174                     beginAudit(nestedObj, currentUri, visited);
175                 } catch (AAIUnknownObjectException e) {
176                     LOGGER.warn("Skipping nested enpoint for " + propName + " (Unknown Object) "
177                             + LogFormatTools.getStackTop(e));
178                 }
179             }
180         }
181
182     }
183
184     /**
185      * Populate logical name.
186      *
187      * @param obj the obj
188      * @param uri the uri
189      * @param currentUri the current uri
190      */
191     private void populateLogicalName(Introspector obj, String uri, String currentUri) {
192
193         if (obj.getDbName().equals("inventory") || currentUri.split("/").length <= 4
194                 || currentUri.endsWith("relationship-list")) {
195             return;
196         }
197
198         if (uri.endsWith("/relationship-list")) {
199             uri = uri.substring(0, uri.lastIndexOf('/'));
200         }
201
202         String logicalName = "";
203         String keys = "";
204
205         if (!obj.getAllKeys().isEmpty()) {
206
207             Pattern p = Pattern.compile("/\\{[\\w\\d\\-]+\\}/\\{[\\w\\d\\-]+\\}+$");
208             Matcher m = p.matcher(currentUri);
209
210             if (m.find()) {
211                 keys = StringUtils.join(obj.getAllKeys(), "-and-");
212             } else {
213                 keys = StringUtils.join(obj.getAllKeys(), "-or-");
214             }
215             keys = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, keys);
216             if (!keys.isEmpty()) {
217                 keys = "With" + keys;
218             }
219         }
220
221         logicalName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, obj.getDbName()) + keys;
222
223         if (endpointToLogicalName.containsKey(uri) && uri.endsWith("}")) {
224             logicalName = logicalName + "From" + endpointToLogicalName.get(uri);
225         } else if (endpointToLogicalName.containsKey(uri.substring(0, uri.lastIndexOf('/')))) {
226             logicalName = logicalName + "From" + endpointToLogicalName.get(uri.substring(0, uri.lastIndexOf('/')));
227         }
228
229         endpointToLogicalName.put(currentUri, logicalName);
230
231     }
232
233     /**
234      * Gets the logical names.
235      *
236      * @return the logical names
237      */
238     public Map<String, String> getLogicalNames() {
239
240         return endpointToLogicalName;
241
242     }
243
244     /**
245      * Gets the endpoints.
246      *
247      * @return the endpoints
248      */
249     public List<String> getEndpoints() {
250
251         return this.getEndpoints("");
252
253     }
254
255     /**
256      * Gets the endpoints.
257      *
258      * @param filterOut the filter out
259      * @return the endpoints
260      */
261     public List<String> getEndpoints(String filterOut) {
262         List<String> result = new ArrayList<>();
263         Pattern p = null;
264         Matcher m = null;
265         if (!filterOut.equals("")) {
266             p = Pattern.compile(filterOut);
267         }
268         for (String s : endpoints) {
269             if (p != null) {
270                 m = p.matcher(s);
271                 if (m.find()) {
272                     continue;
273                 }
274             }
275
276             result.add(s);
277         }
278
279         return result;
280
281     }
282
283     /**
284      * {@inheritDoc}
285      */
286     @Override
287     public String toString() {
288         StringBuilder sb = new StringBuilder();
289         for (String s : endpoints) {
290             sb.append(s + "\n");
291         }
292         return sb.toString();
293
294     }
295
296     /**
297      * To string.
298      *
299      * @param filterOut the filter out
300      * @return the string
301      */
302     public String toString(String filterOut) {
303         StringBuilder sb = new StringBuilder();
304         Pattern p = Pattern.compile(filterOut);
305         Matcher m = null;
306         for (String s : endpoints) {
307             m = p.matcher(s);
308             if (!m.find()) {
309                 sb.append(s + "\n");
310             }
311         }
312         return sb.toString();
313     }
314
315 }