Update the license for 2017-2018 license
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / parsers / uri / URIParser.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.parsers.uri;
21
22 import org.onap.aai.exceptions.AAIException;
23 import org.onap.aai.introspection.Introspector;
24 import org.onap.aai.introspection.Loader;
25 import org.onap.aai.introspection.LoaderFactory;
26 import org.onap.aai.introspection.Version;
27 import org.onap.aai.logging.ErrorLogHelper;
28 import org.onap.aai.parsers.exceptions.DoesNotStartWithValidNamespaceException;
29 import org.onap.aai.rest.RestTokens;
30 import org.onap.aai.schema.enums.ObjectMetadata;
31 import org.onap.aai.serialization.db.EdgeType;
32 import org.onap.aai.util.AAIConfig;
33 import org.springframework.web.util.UriUtils;
34
35 import javax.ws.rs.core.MultivaluedHashMap;
36 import javax.ws.rs.core.MultivaluedMap;
37 import javax.ws.rs.core.UriBuilder;
38 import java.io.UnsupportedEncodingException;
39 import java.net.URI;
40 import java.util.Set;
41
42
43 /**
44  * The Class URIParser.
45  */
46 public class URIParser {
47         
48         private URI uri = null;
49
50         protected Loader loader = null;
51         
52         protected Loader originalLoader = null;
53         
54         private URI originalURI = null;
55         
56         private MultivaluedMap<String, String> queryParams = null;
57         
58         
59         /**
60          * Instantiates a new URI parser.
61          *
62          * @param loader the loader
63          * @param uri the uri
64          */
65         public URIParser(Loader loader, URI uri) {
66                 this.uri = uri;
67
68                 String currentVersion = "v7";
69                 this.originalLoader = loader;
70                 try {
71                         currentVersion = AAIConfig.get("aai.default.api.version");
72                 } catch (AAIException e) {
73                         ErrorLogHelper.logException(e);
74                 }
75
76                 //Load the latest version because we need it for cloud region
77
78                         this.loader = loader;
79                 }
80         
81         /**
82          * Instantiates a new URI parser.
83          *
84          * @param loader the loader
85          * @param uri the uri
86          * @param queryParams the query params
87          */
88         public URIParser(Loader loader, URI uri, MultivaluedMap<String, String> queryParams) {
89                 this(loader, uri);
90                 this.queryParams = queryParams;
91         }
92
93         public Loader getLoader() {
94                 
95                 return this.loader;
96                 
97         }
98         
99         /**
100          * Gets the original URI.
101          *
102          * @return the original URI
103          */
104         public URI getOriginalURI() {
105                 return this.originalURI;
106         }
107         
108         /**
109          * Parses the.
110          *
111          * @param p the p
112          * @throws UnsupportedEncodingException the unsupported encoding exception
113          * @throws AAIException the AAI exception
114          */
115         public void parse(Parsable p) throws UnsupportedEncodingException, AAIException {
116                 try {
117                         boolean isRelative = false;
118                         uri = this.trimURI(uri);
119                         uri = handleCloudRegion(p.getCloudRegionTransform(), uri);
120                         if (p.useOriginalLoader()) {
121                                 this.loader = this.originalLoader;
122                         }
123                         this.originalURI  = UriBuilder.fromPath(uri.getRawPath()).build();
124                         if (uri.getRawPath().startsWith("./")) {
125                                 uri = new URI(uri.getRawPath().replaceFirst("\\./", ""));
126                                 isRelative = true;
127                         }
128                         String[] parts = uri.getRawPath().split("/");
129                         Introspector validNamespaces = loader.introspectorFromName("inventory");
130                         Set<String> keys = null;
131                         String part = "";
132                         Introspector previousObj = null;
133                         EdgeType type = EdgeType.TREE;
134                         for (int i = 0; i < parts.length;) {
135                                 part = parts[i];
136                                 Introspector introspector = null;
137                                 if (part.equals(RestTokens.COUSIN.toString())) {
138                                         if (i == parts.length-1) {
139                                                 throw new AAIException("AAI_3000", uri + " not a valid path. Cannot end in " + RestTokens.COUSIN);
140                                         }
141                                         introspector = loader.introspectorFromName(parts[i+1]);
142                                         if(null == previousObj) {
143                                                 throw new AAIException("AAI_3001");
144                                         }
145                                         if (previousObj.isContainer() && introspector.isContainer()) {
146                                                 throw new AAIException("AAI_3000", uri + " not a valid path. Cannot chain plurals together");
147                                         }
148                                         MultivaluedMap<String, String> uriKeys = new MultivaluedHashMap<>();
149                                         if (i == parts.length-2 && queryParams != null) {
150                                                 Set<String> queryKeys = queryParams.keySet();
151                                                 for (String key : queryKeys) {
152                                                         uriKeys.put(key, queryParams.get(key));
153                                                         
154                                                 }
155                                         }
156                                         if (introspector.isContainer()) {
157                                                 boolean isFinalContainer = i == parts.length-2;
158                                                 p.processContainer(introspector, EdgeType.COUSIN, uriKeys, isFinalContainer);
159                                         }
160                                         previousObj = introspector;
161                                         type = EdgeType.COUSIN;
162                                         i+=2;
163                                         continue;
164                                 }
165                                 introspector = loader.introspectorFromName(part);
166                                 if (introspector != null) {
167                                         
168                                         //previous has current as property
169                                         if (previousObj != null && !previousObj.hasChild(introspector) && !previousObj.getDbName().equals("nodes")) {
170                                                 throw new AAIException("AAI_3001", uri + " not a valid path. " + part + " not valid");
171                                         } else if (previousObj == null) {
172                                                 String abstractType = introspector.getMetadata(ObjectMetadata.ABSTRACT);
173                                                 if (abstractType == null) {
174                                                         abstractType = "";
175                                                 }
176                                                 //first time through, make sure it starts from a namespace
177                                                 //ignore abstract types
178                                                 if (!isRelative && !abstractType.equals("true") && !validNamespaces.hasChild(introspector)) {
179                                                         throw new DoesNotStartWithValidNamespaceException( uri + " not a valid path. It does not start from a valid namespace");
180                                                 }
181                                         }
182                                         
183                                         keys = introspector.getKeys();
184                                         if (keys.size() > 0) {
185                                                 MultivaluedMap<String, String> uriKeys = new MultivaluedHashMap<>();
186                                                 i++;
187                                                 if (i == parts.length && queryParams != null) {
188                                                         Set<String> queryKeys = queryParams.keySet();
189                                                         for (String key : queryKeys) {
190                                                                 uriKeys.put(key, queryParams.get(key));
191                                                         }
192                                                 } else {
193                                                         for (String key : keys) {
194                                                                 part =  UriUtils.decode(parts[i], "UTF-8");
195                                                                 
196                                                                 introspector.setValue(key, part);
197                                                                 
198                                                                 //skip this for further processing
199                                                                 i++;
200                                                         }
201                                                 }
202                                                 
203                                                 p.processObject(introspector, type, uriKeys);
204                                                 type = EdgeType.TREE;
205                                         } else if (introspector.isContainer()) {
206                                                 boolean isFinalContainer = i == parts.length-1;
207                                                 MultivaluedMap<String, String> uriKeys = new MultivaluedHashMap<>();
208                                                 
209                                                 if (isFinalContainer && queryParams != null) {
210                                                         Set<String> queryKeys = queryParams.keySet();
211                                                         for (String key : queryKeys) {
212                                                                 uriKeys.put(key, queryParams.get(key));
213                                                                 
214                                                         }
215                                                 }
216                                                 p.processContainer(introspector, type, uriKeys, isFinalContainer);
217                                                 
218                                                 i++; 
219                                         } else {
220                                                 p.processNamespace(introspector);
221                                                 //namespace case
222                                                 i++;
223                                         }
224                                         previousObj = introspector;
225                                 } else {
226                                         //invalid item found should log
227                                         //original said bad path
228                                         throw new AAIException("AAI_3001", "invalid item found in path: " + part);
229                                 }
230                         }
231                 } catch (AAIException e) {
232                         throw e;
233                 } catch (Exception e) {
234                         throw new AAIException("AAI_3001", e);
235                 }
236         }
237         
238         public boolean validate() throws UnsupportedEncodingException, AAIException {
239                 this.parse(new URIValidate());
240                 return true;
241         }
242         /**
243          * Handle cloud region.
244          *
245          * @param action the action
246          * @param uri the uri
247          * @return the uri
248          */
249         protected URI handleCloudRegion(String action, URI uri) {
250
251                         return uri;
252
253         }
254         
255         /**
256          * Trim URI.
257          *
258          * @param uri the uri
259          * @return the uri
260          */
261         protected URI trimURI(URI uri) {
262                 
263                 String result = uri.getRawPath();
264                 if (result.startsWith("/")) {
265                         result = result.substring(1, result.length());
266                 }
267                 
268                 if (result.endsWith("/")) {
269                         result = result.substring(0, result.length() - 1);
270                 }
271                 
272                 result = result.replaceFirst("aai/v\\d+/", "");
273                 
274                 return UriBuilder.fromPath(result).build();
275         }
276
277 }