8d88a4a596f8a3a11330006ab0d1f5c6e408a560
[aai/cacher.git] /
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.cacher.injestion.parser.strategy.aai.dmaap;
21
22 import com.att.eelf.configuration.EELFLogger;
23 import com.att.eelf.configuration.EELFManager;
24 import com.google.gson.JsonArray;
25 import com.google.gson.JsonElement;
26 import com.google.gson.JsonObject;
27 import org.onap.aai.cacher.injestion.parser.strategy.AAIResourceGetAllPayloadParserStrategy;
28 import org.onap.aai.cacher.injestion.parser.strategy.aai.AAIResourcesUriTemplates;
29 import org.onap.aai.cacher.injestion.parser.strategy.aai.AAIUriSegment;
30 import org.onap.aai.cacher.model.CacheEntry;
31 import org.springframework.beans.factory.annotation.Autowired;
32 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
33 import org.springframework.context.annotation.Scope;
34 import org.springframework.stereotype.Component;
35 import org.springframework.util.LinkedMultiValueMap;
36 import org.springframework.util.MultiValueMap;
37
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Optional;
42 import java.util.stream.Collectors;
43
44 /**
45  * AAI resource get all parser strategy
46  */
47 @Component(value = "aai-resource-dmaap")
48 @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
49 public class AAIResourceDmaapParserStrategy extends AAIResourceGetAllPayloadParserStrategy {
50     
51     private final static EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIResourceDmaapParserStrategy.class);
52
53     @Autowired
54     public AAIResourceDmaapParserStrategy(AAIResourcesUriTemplates aaiResourcesUriTemplates) {
55         super(aaiResourcesUriTemplates);
56     }
57
58     /**
59      * Parses aai resources specific payloads generating the details for caching.
60      *
61      * @param originalKey
62      * @param jsonObject
63      * @return
64      */
65     @Override
66     public List<CacheEntry> process(String originalKey, JsonObject jsonObject) {
67         final List<CacheEntry> cacheEntries;
68
69         JsonObject header = jsonObject.getAsJsonObject("event-header");
70         String topEntityType = header.get("top-entity-type").getAsString();
71         String fullUri = header.get("entity-link").getAsString();
72         if ( fullUri.endsWith("/")) {
73             fullUri = fullUri.substring(0, fullUri.length() - 1);
74         }
75         String entityUri = aaiResourcesUriTemplates.getAAIUriFromEntityUri(fullUri);
76         String fullUriPrefix = aaiResourcesUriTemplates.getAAIUriFromEntityUriPrefix(fullUri);
77
78         DmaapAction actionType = DmaapAction.valueOf(header.get("action").getAsString());
79
80         List<AAIUriSegment> uriSegments = aaiResourcesUriTemplates.getAaiUriSegments(entityUri);
81
82         // get base uri so if is top lvl use "" else go 1 back from current node type. to reuse exist functions.
83         String baseUri = getBaseUri(uriSegments);
84
85         // get wrapped wrap obj it looks like a get-all result with 1
86         // will wrap address lists even though they do not normally have a wrapper
87         JsonObject wrappedEntityObject = getWrappedEntityObject(jsonObject.getAsJsonObject("entity"), uriSegments);
88
89         // get cache entries
90         cacheEntries = internalProcess(topEntityType, wrappedEntityObject, baseUri);
91
92         // modify action to map to dmaap event type
93         cacheEntries.forEach(cacheEntry -> cacheEntry.setDbAction(actionType.getDbAction()));
94
95         // cache entries for relationships
96         MultiValueMap<String, AAIRelatedToDetails> cacheEntriesRelationships =
97                 getFromRelationshipFullUriToRelationshipObj(cacheEntries, fullUriPrefix, actionType);
98
99         if (jsonObject.has("existing-obj")) {
100             MultiValueMap<String, AAIRelatedToDetails> existingCacheEntriesRelationships =
101                     getFromRelationshipFullUriToRelationshipObj(
102                             internalProcess(topEntityType, jsonObject.getAsJsonObject("existing-obj"), baseUri),
103                             fullUriPrefix,
104                             actionType
105                     );
106             adjustRelationshipsBasedOnExisting(existingCacheEntriesRelationships, cacheEntriesRelationships);
107
108         }
109
110         cacheEntries.addAll(getRelationshipCacheEntries(cacheEntriesRelationships));
111
112         getParentUpdateCacheEntryIfNeeded(topEntityType, entityUri, actionType, uriSegments).ifPresent(cacheEntries::add);
113
114         return cacheEntries;
115     }
116
117     private Optional<CacheEntry> getParentUpdateCacheEntryIfNeeded(String topEntityType, String entityUri, DmaapAction actionType, List<AAIUriSegment> uriSegments) {
118
119         if (uriSegments.size() <= 1) {
120             return Optional.empty();
121         }
122
123         switch (actionType) {
124             case DELETE:
125                 return Optional.of(getParentUpdateCacheEntry(topEntityType, entityUri, actionType, uriSegments));
126             case CREATE:
127                 return Optional.of(getParentUpdateCacheEntry(topEntityType, entityUri, DmaapAction.UPDATE, uriSegments));
128             default:
129                 return Optional.empty();
130         }
131     }
132
133     private CacheEntry getParentUpdateCacheEntry(String topEntityType, String entityUri, DmaapAction actionType, List<AAIUriSegment> uriSegments) {
134         String parentUri = String.join(
135                 "",
136                 uriSegments.stream().limit(uriSegments.size()-1).map(AAIUriSegment::getSegment).collect(Collectors.toList()));
137         JsonObject findQuery = new JsonObject();
138         findQuery.addProperty("_id", parentUri);
139         JsonObject nestedFindQuery = new JsonObject();
140         nestedFindQuery.addProperty("_id", parentUri);
141         StringBuilder nestedField = new StringBuilder();
142         uriSegments.get(uriSegments.size()-1).getSegmentPlural().ifPresent(plural -> nestedField.append(plural).append("."));
143         nestedField.append(uriSegments.get(uriSegments.size()-1).getSegmentSingular());
144         JsonObject nestedIdentifier = new JsonObject();
145         JsonArray ja = new JsonArray();
146         ja.add(entityUri);
147         nestedIdentifier.add("$in", ja);
148         return CacheEntry.CacheEntryBuilder.createCacheEntry()
149                 .inCollection(topEntityType)
150                 .withDbAction(actionType.getDbAction())
151                 .withId(parentUri)
152                 .isNested(true)
153                 .isNestedPayloadString(true)
154                 .withNestedString(entityUri)
155                 .withFindQuery(findQuery)
156                 .withNestedFind(nestedFindQuery)
157                 .withNestedField(nestedField.toString())
158                 .withNestedFieldIdentifierObj(nestedIdentifier)
159                 .build();
160     }
161
162     private List<CacheEntry> getRelationshipCacheEntries(MultiValueMap<String, AAIRelatedToDetails> cacheEntriesRelationships) {
163         final List<CacheEntry> cacheEntries = new ArrayList<>();
164         JsonObject relatedToObj;
165         for (Map.Entry<String, List<AAIRelatedToDetails>> relationship : cacheEntriesRelationships.entrySet()) {
166             for (AAIRelatedToDetails aaiRelatedToDetails : relationship.getValue()) {
167                 relatedToObj = fullUriToRelationshipObj(relationship.getKey(), aaiRelatedToDetails.getLabel());
168                 cacheEntries.add(generateRelationshipCacheEntry(relatedToObj, aaiRelatedToDetails.getActionType(),
169                         aaiRelatedToDetails.getFullUri()));
170             }
171         }
172         return cacheEntries;
173     }
174
175     private CacheEntry generateRelationshipCacheEntry(JsonObject entity, DmaapAction actionType, String fullUri) {
176
177         String uri = aaiResourcesUriTemplates.getAAIUriFromEntityUri(fullUri);
178         List<AAIUriSegment> uriSegmentList = aaiResourcesUriTemplates.getAaiUriSegments(uri);
179         String collection = uriSegmentList.get(0).getSegmentSingular();
180         JsonObject findQuery = new JsonObject();
181         findQuery.addProperty("_id", uri);
182         JsonObject nestedFindQuery = new JsonObject();
183         nestedFindQuery.addProperty("_id", uri);
184         nestedFindQuery.addProperty("relationship-list.relationship.related-link", entity.get("related-link").getAsString());
185         String nestedField = "relationship-list.relationship";
186         JsonObject nestedIdentifier = new JsonObject();
187         nestedIdentifier.addProperty("related-link", entity.get("related-link").getAsString());
188
189         return CacheEntry.CacheEntryBuilder.createCacheEntry().inCollection(collection).withDbAction(actionType.getDbAction())
190                 .withId(uri).isNested(true).withPayload(entity).withFindQuery(findQuery)
191                 .withNestedFind(nestedFindQuery).withNestedField(nestedField)
192                 .withNestedFieldIdentifierObj(nestedIdentifier).build();
193     }
194
195     private void adjustRelationshipsBasedOnExisting(MultiValueMap<String, AAIRelatedToDetails> existingCacheEntriesRelationships,
196                                                     MultiValueMap<String, AAIRelatedToDetails> cacheEntriesRelationships) {
197         existingCacheEntriesRelationships.forEach((k, v) -> {
198             if (cacheEntriesRelationships.containsKey(k)) {
199                 v.forEach(oldA -> {
200                     int found = -1;
201                     for (int i = 0; i < cacheEntriesRelationships.get(k).size(); i++) {
202                         if (cacheEntriesRelationships.get(k).get(i).getFullUri().equals(oldA.getFullUri())) {
203                             found = i;
204                             break;
205                         }
206                     }
207                     if (found != -1) {
208                         cacheEntriesRelationships.get(k).remove(cacheEntriesRelationships.get(k).get(found));
209                     } else {
210                         oldA.setActionType(DmaapAction.DELETE);
211                         cacheEntriesRelationships.get(k).add(oldA);
212                     }
213                 });
214             } else {
215                 v.forEach(aaiRelatedToDetails -> {
216                     aaiRelatedToDetails.setActionType(DmaapAction.DELETE);
217                     cacheEntriesRelationships.add(k, aaiRelatedToDetails);
218                 });
219             }
220         });
221     }
222
223     private MultiValueMap<String, AAIRelatedToDetails> getFromRelationshipFullUriToRelationshipObj(
224             List<CacheEntry> cacheEntries,
225             String fullUriPrefix,
226             DmaapAction actionType) {
227         final MultiValueMap<String, AAIRelatedToDetails> relationshipMapping = new LinkedMultiValueMap<>();
228         for (CacheEntry cacheEntry : cacheEntries) {
229             for (Map.Entry<String, JsonElement> e : cacheEntry.getPayload().entrySet()) {
230                 if (e.getKey().equals("relationship-list") && e.getValue().isJsonObject()) {
231                     JsonArray relationships = e.getValue().getAsJsonObject().getAsJsonArray("relationship");
232                     for (JsonElement relationship : relationships) {
233                         relationshipMapping.add(fullUriPrefix + cacheEntry.getId(), new AAIRelatedToDetails(
234                                 relationship.getAsJsonObject().get("related-link").getAsString(),
235                                 relationship.getAsJsonObject().get("relationship-label").getAsString(), actionType));
236                     }
237                 }
238             }
239         }
240         return relationshipMapping;
241     }
242
243     /**
244      * Given fullUri uri generate an aai relationship obj
245      *
246      * @param fullUri
247      * @return
248      */
249     protected JsonObject fullUriToRelationshipObj(String fullUri, String label) {
250         final JsonObject relObj = new JsonObject();
251         final JsonArray relData = new JsonArray();
252         String uri = aaiResourcesUriTemplates.getAAIUriFromEntityUri(fullUri);
253         List<AAIUriSegment> uriSegmentList = aaiResourcesUriTemplates.getAaiUriSegments(uri);
254
255         relObj.addProperty("related-to", uriSegmentList.get(uriSegmentList.size() - 1).getSegmentSingular());
256         if (label != null) {
257             relObj.addProperty("relationship-label", label);
258         }
259         relObj.addProperty("related-link", fullUri);
260
261         for (AAIUriSegment aaiUriSegment : uriSegmentList) {
262             aaiUriSegment.getSegmentKeyValues().forEach((k, v) -> {
263                 JsonObject relDataEntry;
264                 relDataEntry = new JsonObject();
265                 relDataEntry.addProperty("relationship-key", aaiUriSegment.getSegmentSingular() + "." + k);
266                 relDataEntry.addProperty("relationship-value", v);
267                 relData.add(relDataEntry);
268             });
269         }
270         relObj.add("relationship-data", relData);
271
272         return relObj;
273     }
274
275     private JsonObject getWrappedEntityObject(JsonObject dmaapEntity, List<AAIUriSegment> uriSegments) {
276         JsonObject objectWrapper = new JsonObject();
277         JsonArray arrayWrapper = new JsonArray();
278         String arrayKey = uriSegments.get(0).getSegmentSingular();
279         JsonObject entityBody = dmaapEntity.getAsJsonObject();
280
281         if (uriSegments.size() > 1) {
282             Optional<String> segmentPlural;
283             String segmentSingular;
284             String jsonStr;
285             JsonObject jsonObj;
286             JsonArray jsonArray;
287             JsonElement jsonElement;
288
289             for (int i = 1; i < uriSegments.size(); i++) {
290
291                 if (uriSegments.get(i).getSegmentPlural().isPresent()) {
292                     segmentPlural = uriSegments.get(i).getSegmentPlural();
293                     segmentSingular = uriSegments.get(i).getSegmentSingular();
294                     if ( segmentSingular.equals("cvlan-tag")) {
295                             // map to what is in the entity
296                         segmentSingular = "cvlan-tag-entry";
297                     }
298                     jsonObj = entityBody.getAsJsonObject(uriSegments.get(i).getSegmentPlural().get());
299                     jsonArray = jsonObj.getAsJsonArray(segmentSingular);
300                     if ( jsonArray == null ) {
301                         LOGGER.error("failed in getWrappedEntityObject " + segmentSingular + " not found in " + jsonObj );
302                         // exception expected for missing template
303                     }
304                     entityBody = jsonArray.get(0).getAsJsonObject();
305                     arrayKey = uriSegments.get(i).getSegmentSingular();
306                 } else {
307                     entityBody = entityBody.getAsJsonArray(uriSegments.get(i).getSegmentSingular()).get(0).getAsJsonObject();
308                     arrayKey = uriSegments.get(i).getSegmentSingular();
309                 }
310
311             }
312         }
313         arrayWrapper.add(entityBody);
314         objectWrapper.add(arrayKey, arrayWrapper);
315         return objectWrapper;
316     }
317
318     private String getBaseUri(List<AAIUriSegment> uriSegments) {
319         if (uriSegments.isEmpty() || uriSegments.size() == 1) {
320             return "";
321         }
322         return String.join("", uriSegments.subList(0, uriSegments.size()-1).stream().map(AAIUriSegment::getSegment).collect(Collectors.toList()));
323     }
324
325
326
327 }