874397741390ece53707d6f6629f061c08c0ea25
[aai/aai-common.git] / aai-core / src / main / java / org / openecomp / aai / parsers / uri / URIParser.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * org.openecomp.aai
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
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
21 package org.openecomp.aai.parsers.uri;
22
23 import java.io.UnsupportedEncodingException;
24 import java.net.URI;
25 import java.util.Set;
26
27 import javax.ws.rs.core.MultivaluedHashMap;
28 import javax.ws.rs.core.MultivaluedMap;
29 import javax.ws.rs.core.UriBuilder;
30
31 import org.springframework.web.util.UriUtils;
32
33 import org.openecomp.aai.exceptions.AAIException;
34 import org.openecomp.aai.introspection.Introspector;
35 import org.openecomp.aai.introspection.Loader;
36 import org.openecomp.aai.introspection.LoaderFactory;
37 import org.openecomp.aai.introspection.Version;
38 import org.openecomp.aai.logging.ErrorLogHelper;
39 import org.openecomp.aai.schema.enums.ObjectMetadata;
40 import org.openecomp.aai.util.AAIConfig;
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
134                         for (int i = 0; i < parts.length;) {
135                                 part = parts[i];
136                                 Introspector introspector = null;
137                                 introspector = loader.introspectorFromName(part);
138                                 if (introspector != null) {
139                                         
140                                         //previous has current as property
141                                         if (previousObj != null && !previousObj.hasChild(introspector) && !previousObj.getDbName().equals("nodes")) {
142                                                 throw new AAIException("AAI_3001", uri + " not a valid path. " + part + " not valid");
143                                         } else if (previousObj == null) {
144                                                 String abstractType = introspector.getMetadata(ObjectMetadata.ABSTRACT);
145                                                 if (abstractType == null) {
146                                                         abstractType = "";
147                                                 }
148                                                 //first time through, make sure it starts from a namespace
149                                                 //ignore abstract types
150                                                 if (!isRelative && !abstractType.equals("true") && !validNamespaces.hasChild(introspector)) {
151                                                         throw new AAIException("AAI_3000", uri + " not a valid path. It does not start from a valid namespace");
152                                                 }
153                                         }
154                                         
155                                         keys = introspector.getKeys();
156                                         if (keys.size() > 0) {
157                                                 MultivaluedMap<String, String> uriKeys = new MultivaluedHashMap<>();
158                                                 i++;
159                                                 if (i == parts.length && queryParams != null) {
160                                                         Set<String> queryKeys = queryParams.keySet();
161                                                         for (String key : queryKeys) {
162                                                                 uriKeys.put(key, queryParams.get(key));
163                                                         }
164                                                 } else {
165                                                         for (String key : keys) {
166                                                                 part =  UriUtils.decode(parts[i], "UTF-8");
167                                                                 
168                                                                 introspector.setValue(key, part);
169                                                                 
170                                                                 //skip this for further processing
171                                                                 i++;
172                                                         }
173                                                 }
174                                                 
175                                                 p.processObject(introspector, uriKeys);
176         
177                                         } else if (introspector.isContainer()) {
178                                                 boolean isFinalContainer = i == parts.length-1;
179                                                 MultivaluedMap<String, String> uriKeys = new MultivaluedHashMap<>();
180                                                 
181                                                 if (isFinalContainer && queryParams != null) {
182                                                         Set<String> queryKeys = queryParams.keySet();
183                                                         for (String key : queryKeys) {
184                                                                 uriKeys.put(key, queryParams.get(key));
185                                                                 
186                                                         }
187                                                 }
188                                                 p.processContainer(introspector, uriKeys, isFinalContainer);
189                                                 
190                                                 i++; 
191                                         } else {
192                                                 p.processNamespace(introspector);
193                                                 //namespace case
194                                                 i++;
195                                         }
196                                         previousObj = introspector;
197                                 } else {
198                                         //invalid item found should log
199                                         //original said bad path
200                                         throw new AAIException("AAI_3001", "invalid item found in path: " + part);
201                                 }
202                         }
203                 } catch (AAIException e) {
204                         throw e;
205                 } catch (Exception e) {
206                         throw new AAIException("AAI_3001", e);
207                 }
208         }
209         
210         public boolean validate() throws UnsupportedEncodingException, AAIException {
211                 this.parse(new URIValidate());
212                 return true;
213         }
214         /**
215          * Handle cloud region.
216          *
217          * @param action the action
218          * @param uri the uri
219          * @return the uri
220          */
221         protected URI handleCloudRegion(String action, URI uri) {
222                 
223                 return uri;
224                 
225         }
226         
227         /**
228          * Trim URI.
229          *
230          * @param uri the uri
231          * @return the uri
232          */
233         protected URI trimURI(URI uri) {
234                 
235                 String result = uri.getRawPath();
236                 if (result.startsWith("/")) {
237                         result = result.substring(1, result.length());
238                 }
239                 
240                 if (result.endsWith("/")) {
241                         result = result.substring(0, result.length() - 1);
242                 }
243                 
244                 result = result.replaceFirst("aai/v\\d+/", "");
245                 
246                 return UriBuilder.fromPath(result).build();
247         }
248
249 }