2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 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
 
  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.onap.so.client.graphinventory;
 
  23 import java.util.HashMap;
 
  24 import java.util.List;
 
  26 import java.util.Optional;
 
  27 import javax.ws.rs.NotFoundException;
 
  28 import javax.ws.rs.core.GenericType;
 
  29 import org.onap.aai.domain.yang.Relationship;
 
  30 import org.onap.so.client.graphinventory.entities.GraphInventoryEdgeLabel;
 
  31 import org.onap.so.client.graphinventory.entities.uri.GraphInventoryResourceUri;
 
  32 import org.onap.so.client.graphinventory.entities.uri.GraphInventorySingleResourceUri;
 
  33 import org.onap.so.client.graphinventory.exceptions.BulkProcessFailed;
 
  34 import org.slf4j.Logger;
 
  35 import org.slf4j.LoggerFactory;
 
  37 public abstract class GraphInventoryTransactionClient<Self, Uri extends GraphInventoryResourceUri<?, ?>, SingleUri extends GraphInventorySingleResourceUri<?, ?, ?, ?>, EdgeLabel extends GraphInventoryEdgeLabel> {
 
  39     protected static Logger logger = LoggerFactory.getLogger(GraphInventoryTransactionClient.class);
 
  41     protected int actionCount = 0;
 
  43     protected final GraphInventoryPatchConverter patchConverter = new GraphInventoryPatchConverter();
 
  45     protected GraphInventoryTransactionClient() {}
 
  48      * creates a new object in A&AI
 
  50      * @param obj - can be any object which will marshal into a valid A&AI payload
 
  54     public Self create(SingleUri uri, Object obj) {
 
  55         this.put(uri.build().toString(), obj);
 
  56         incrementActionAmount();
 
  61      * creates a new object in A&AI with no payload body
 
  66     public Self createEmpty(SingleUri uri) {
 
  67         this.put(uri.build().toString(), new HashMap<String, String>());
 
  68         incrementActionAmount();
 
  73      * Will automatically create the object if it does not exist
 
  75      * @param obj - Optional object which serializes to a valid GraphInventory payload
 
  79     public Self createIfNotExists(SingleUri uri, Optional<Object> obj) {
 
  80         if (!this.exists((Uri) uri)) {
 
  81             if (obj.isPresent()) {
 
  82                 this.create(uri, obj.get());
 
  84                 this.createEmpty(uri);
 
  92      * Adds a relationship between two objects in A&AI
 
  98     public Self connect(SingleUri uriA, SingleUri uriB) {
 
  99         GraphInventorySingleResourceUri uriAClone = uriA.clone();
 
 100         this.put(uriAClone.relationshipAPI().build().toString(), this.buildRelationship(uriB));
 
 101         incrementActionAmount();
 
 106      * relationship between multiple objects in A&AI - connects A to all objects specified in list
 
 112     public Self connect(SingleUri uriA, List<SingleUri> uris) {
 
 113         for (SingleUri uri : uris) {
 
 114             this.connect(uriA, uri);
 
 120      * relationship between multiple objects in A&AI - connects A to all objects specified in list
 
 126     public Self connect(SingleUri uriA, SingleUri uriB, EdgeLabel label) {
 
 127         GraphInventorySingleResourceUri uriAClone = uriA.clone();
 
 128         this.put(uriAClone.relationshipAPI().build().toString(), this.buildRelationship(uriB, label));
 
 133      * relationship between multiple objects in A&AI - connects A to all objects specified in list
 
 139     public Self connect(SingleUri uriA, List<SingleUri> uris, EdgeLabel label) {
 
 140         for (SingleUri uri : uris) {
 
 141             this.connect(uriA, uri, label);
 
 147      * Removes relationship from two objects in A&AI
 
 153     public Self disconnect(SingleUri uriA, SingleUri uriB) {
 
 154         GraphInventorySingleResourceUri uriAClone = uriA.clone();
 
 155         this.delete(uriAClone.relationshipAPI().build().toString(), this.buildRelationship(uriB));
 
 156         incrementActionAmount();
 
 161      * Removes relationship from multiple objects - disconnects A from all objects specified in list
 
 167     public Self disconnect(SingleUri uriA, List<SingleUri> uris) {
 
 168         for (SingleUri uri : uris) {
 
 169             this.disconnect(uriA, uri);
 
 175      * Deletes object from A&AI. Automatically handles resource-version.
 
 180     public Self delete(SingleUri uri) {
 
 181         Map<String, Object> result = this.get(new GenericType<Map<String, Object>>() {}, (Uri) uri)
 
 182                 .orElseThrow(() -> new NotFoundException(uri.build() + " does not exist in " + this.getGraphDBName()));
 
 183         String resourceVersion = (String) result.get("resource-version");
 
 184         this.delete(uri.resourceVersion(resourceVersion).build().toString());
 
 185         incrementActionAmount();
 
 189     protected abstract <T> Optional<T> get(GenericType<T> genericType, Uri clone);
 
 191     protected abstract boolean exists(Uri uri);
 
 193     protected abstract String getGraphDBName();
 
 195     protected abstract void put(String uri, Object body);
 
 197     protected abstract void delete(String uri);
 
 199     protected abstract void delete(String uri, Object obj);
 
 201     protected abstract void patch(String uri, Object body);
 
 204      * @param obj - can be any object which will marshal into a valid A&AI payload
 
 208     public Self update(Uri uri, Object obj) {
 
 210         final String payload = getPatchConverter().convertPatchFormat(obj);
 
 211         this.patch(uri.build().toString(), payload);
 
 212         incrementActionAmount();
 
 216     private void incrementActionAmount() {
 
 221      * Executes all created transactions in A&AI
 
 223      * @throws BulkProcessFailed
 
 225     public abstract void execute() throws BulkProcessFailed;
 
 229      * Executes all created transactions in A&AI, with optional dry run flag
 
 231      * @throws BulkProcessFailed
 
 233     public abstract void execute(boolean dryrun) throws BulkProcessFailed;
 
 235     private Relationship buildRelationship(SingleUri uri) {
 
 236         return buildRelationship(uri, Optional.empty());
 
 239     private Relationship buildRelationship(SingleUri uri, EdgeLabel label) {
 
 240         return buildRelationship(uri, Optional.of(label));
 
 243     private Relationship buildRelationship(SingleUri uri, Optional<EdgeLabel> label) {
 
 244         final Relationship result = new Relationship();
 
 245         result.setRelatedLink(uri.build().toString());
 
 246         if (label.isPresent()) {
 
 247             result.setRelationshipLabel(label.toString());
 
 252     protected GraphInventoryPatchConverter getPatchConverter() {
 
 253         return this.patchConverter;