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() {