2 * ============LICENSE_START=======================================================
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
11 http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.aai.parsers.relationship;
23 import java.io.UnsupportedEncodingException;
25 import java.net.URISyntaxException;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Optional;
31 import javax.ws.rs.core.UriBuilder;
33 import org.apache.tinkerpop.gremlin.structure.Direction;
35 import org.openecomp.aai.exceptions.AAIException;
36 import org.openecomp.aai.introspection.Introspector;
37 import org.openecomp.aai.introspection.IntrospectorFactory;
38 import org.openecomp.aai.introspection.Loader;
39 import org.openecomp.aai.introspection.ModelType;
40 import org.openecomp.aai.introspection.Version;
41 import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException;
42 import org.openecomp.aai.parsers.exceptions.AAIIdentityMapParseException;
43 import org.openecomp.aai.parsers.exceptions.AmbiguousMapAAIException;
44 import org.openecomp.aai.parsers.uri.URIParser;
45 import org.openecomp.aai.schema.enums.ObjectMetadata;
46 import org.openecomp.aai.serialization.db.EdgeRule;
47 import org.openecomp.aai.serialization.db.EdgeRules;
48 import org.openecomp.aai.serialization.db.EdgeType;
49 import org.openecomp.aai.workarounds.LegacyURITransformer;
50 import com.att.eelf.configuration.EELFLogger;
51 import com.att.eelf.configuration.EELFManager;
54 * The Class RelationshipToURI.
56 public class RelationshipToURI {
58 private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(RelationshipToURI.class);
60 private Introspector relationship = null;
62 private Loader loader = null;
64 private ModelType modelType = null;
66 private EdgeRules edgeRules = null;
68 private URI uri = null;
70 private LegacyURITransformer urlTransform = null;
73 * Instantiates a new relationship to URI.
75 * @param loader the loader
76 * @param relationship the relationship
77 * @throws UnsupportedEncodingException the unsupported encoding exception
78 * @throws AAIException the AAI exception
80 public RelationshipToURI(Loader loader, Introspector relationship) throws UnsupportedEncodingException, AAIException {
81 this.relationship = relationship;
82 this.modelType = relationship.getModelType();
83 this.edgeRules = EdgeRules.getInstance();
85 this.urlTransform = LegacyURITransformer.getInstance();
95 * @throws UnsupportedEncodingException the unsupported encoding exception
96 * @throws AAIException the AAI exception
98 protected void parse() throws AAIException {
99 String relatedLink = (String)relationship.getValue("related-link");
100 Optional<URI> result;
102 if (loader.getVersion().compareTo(Version.v10) >= 0) {
103 result = processRelatedLink(relatedLink);
104 if (!result.isPresent()) {
105 result = processRelationshipData();
108 result = processRelationshipData();
109 if (!result.isPresent()) {
110 result = processRelatedLink(relatedLink);
113 if (result.isPresent()) {
114 this.uri = result.get();
116 throw new AAIIdentityMapParseException("nothing to parse");
118 } catch (UnsupportedEncodingException | URISyntaxException e) {
119 throw new AAIIdentityMapParseException("Could not parse relationship-list object: " + e.getMessage(), e);
124 private Optional<URI> processRelationshipData() throws AAIException, UnsupportedEncodingException {
125 Optional<URI> result = Optional.empty();
126 StringBuilder uriBuilder = new StringBuilder();
127 List<Object> data = (List<Object>)relationship.getValue("relationship-data");
128 Introspector wrapper;
133 String topLevelType = null;
135 HashMap<String, Introspector> map = new HashMap<>();
136 for (Object datum : data) {
137 wrapper = IntrospectorFactory.newInstance(modelType, datum);
138 key = (String)wrapper.getValue("relationship-key");
139 value = (String)wrapper.getValue("relationship-value");
140 split = key.split("\\.");
141 if (split == null || split.length != 2) {
142 throw new AAIIdentityMapParseException("incorrect format for key must be of the form {node-type}.{property-name}");
146 objectType = split[0];
147 propertyName = split[1];
150 Introspector wrappedObj = loader.introspectorFromName(objectType);
152 if (!wrappedObj.hasProperty(propertyName)) {
153 throw new AAIIdentityMapParseException("invalid property name in map: " + propertyName);
155 if (map.containsKey(objectType)) {
156 wrappedObj = map.get(objectType);
158 map.put(objectType, wrappedObj);
160 if (wrappedObj.getValue(propertyName) == null) {
161 wrappedObj.setValue(propertyName, value);
163 throw new AmbiguousMapAAIException("cannot determine where key/value goes: " + propertyName + "/" + value);
166 if (wrappedObj.getMetadata(ObjectMetadata.NAMESPACE) != null) {
167 if (topLevelType == null) {
168 topLevelType = objectType;
169 } else if (!topLevelType.equals(objectType)){
170 throw new AmbiguousMapAAIException("found two top level nodes of different types: " + topLevelType + " and " + objectType);
173 } catch (AAIUnknownObjectException e) {
174 throw new AAIIdentityMapParseException("invalid object name in map: " + objectType, e);
178 if (!map.isEmpty()) {
179 String startType = (String)relationship.getValue("related-to");
180 List<String> nodeTypes = new ArrayList<>();
181 nodeTypes.addAll(map.keySet());
183 String displacedType;
184 for (int i = 0; i < nodeTypes.size(); i++) {
185 if (nodeTypes.get(i).equals(startType)) {
186 displacedType = nodeTypes.set(nodeTypes.size() - 1, startType);
187 nodeTypes.set(i, displacedType);
191 sortRelationships(nodeTypes, startType, 1);
192 int startTypeIndex = nodeTypes.indexOf(startType);
193 int topLevelIndex = 0;
194 if (topLevelType != null) {
195 topLevelIndex = nodeTypes.indexOf(topLevelType);
197 //remove additional types not needed if they are there
198 List<String> nodeTypesSubList = nodeTypes;
199 if (topLevelIndex != 0) {
200 nodeTypesSubList = nodeTypes.subList(topLevelIndex, startTypeIndex+1);
202 for (String type : nodeTypesSubList) {
203 uriBuilder.append(map.get(type).getURI());
205 if (!nodeTypesSubList.isEmpty()) {
206 result = Optional.of(UriBuilder.fromPath(uriBuilder.toString()).build());
212 private Optional<URI> processRelatedLink(String relatedLink) throws URISyntaxException, UnsupportedEncodingException, AAIIdentityMapParseException {
213 Optional<URI> result = Optional.empty();
214 if (relatedLink != null) {
215 URI resultUri = new URI(relatedLink);
216 String path = resultUri.toString();
217 resultUri = UriBuilder.fromPath(resultUri.getRawPath()).build();
218 URIParser uriParser = new URIParser(this.loader, resultUri);
220 uriParser.validate();
221 } catch (AAIException e) {
222 throw new AAIIdentityMapParseException("related link is invalid: " + relatedLink, e);
224 result = Optional.of(resultUri);
231 * Sort relationships.
233 * @param data the data
234 * @param startType the start type
236 * @return true, if successful
237 * @throws AAIException
239 private boolean sortRelationships(List<String> data, String startType, int i) throws AAIException {
241 if (i == data.size()) {
246 String displacedObject;
249 for (j = (data.size() - i) - 1; j >= 0; j--) {
250 objectType = data.get(j);
252 rule = edgeRules.getEdgeRule(EdgeType.TREE, startType, objectType);
253 direction = rule.getDirection();
254 if (direction != null) {
255 if ((rule.getIsParent().equals("true") && direction.equals(Direction.IN)) || (rule.getIsParent().equals("reverse") && direction.equals(Direction.OUT))) {
256 displacedObject = data.set((data.size() - i) - 1, data.get(j));
257 data.set(j, displacedObject);
258 if (sortRelationships(data, objectType, i+1)) {
261 //continue to process
265 } catch (AAIException e) {
266 //ignore exceptions generated
280 public URI getUri() {