aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
authorPopescu, Serban <serban.popescu@amdocs.com>2019-02-13 10:29:59 -0500
committerSerban Popescu <serban.popescu@amdocs.com>2019-02-13 10:30:26 -0500
commitf60a17c6abb6deef1c24f917488745cbc6e6a566 (patch)
tree3f7e612e4c1c0bcb435e6bbc851f09e8baa3afb7 /src/main/java
parent0c40bcde9facc109ceb8dabb91156df2b4fb4129 (diff)
Performance Improvements for Gizmo bulk API
Use bulk operations with Gizmo/Champ to improve performance. Also allows for HA by allowing Champ to operate in stateless mode Change-Id: I63bbbf8d6071cecb4b22110c477d7dc592026200 Issue-ID: AAI-2147 Signed-off-by: Serban Popescu <serban.popescu@amdocs.com>
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/onap/crud/CrudApplication.java118
-rw-r--r--src/main/java/org/onap/crud/dao/GraphDao.java9
-rw-r--r--src/main/java/org/onap/crud/dao/champ/ChampBulkOp.java116
-rw-r--r--src/main/java/org/onap/crud/dao/champ/ChampBulkPayload.java316
-rw-r--r--src/main/java/org/onap/crud/dao/champ/ChampBulkPayloadResponse.java172
-rw-r--r--src/main/java/org/onap/crud/dao/champ/ChampDao.java151
-rw-r--r--src/main/java/org/onap/crud/logging/CrudServiceMsgs.java8
-rw-r--r--src/main/java/org/onap/crud/service/AbstractGraphDataService.java207
-rw-r--r--src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java227
-rw-r--r--src/main/java/org/onap/crud/service/CrudGraphDataService.java51
10 files changed, 999 insertions, 376 deletions
diff --git a/src/main/java/org/onap/crud/CrudApplication.java b/src/main/java/org/onap/crud/CrudApplication.java
index 3c8e5f7..5815fe7 100644
--- a/src/main/java/org/onap/crud/CrudApplication.java
+++ b/src/main/java/org/onap/crud/CrudApplication.java
@@ -45,67 +45,75 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableSwagger2
@ImportResource({"file:${SERVICE_BEANS}/*.xml"})
public class CrudApplication extends SpringBootServletInitializer{// NOSONAR
- @Autowired
- private Environment env;
+ @Autowired
+ private Environment env;
- public static void main(String[] args) {// NOSONAR
- String keyStorePassword = System.getProperty("KEY_STORE_PASSWORD");
- if(keyStorePassword==null || keyStorePassword.isEmpty()){
- throw new RuntimeException("Env property KEY_STORE_PASSWORD not set");
- }
- HashMap<String, Object> props = new HashMap<>();
- String deobfuscatedKeyStorePassword = keyStorePassword.startsWith("OBF:")?Password.deobfuscate(keyStorePassword):keyStorePassword;
- props.put("server.ssl.key-store-password", deobfuscatedKeyStorePassword);
-
- String trustStoreLocation = System.getProperty("TRUST_STORE_LOCATION");
- String trustStorePassword = System.getProperty("TRUST_STORE_PASSWORD");
- if(trustStoreLocation!=null && trustStorePassword !=null){
- trustStorePassword = trustStorePassword.startsWith("OBF:")?Password.deobfuscate(trustStorePassword):trustStorePassword;
- props.put("server.ssl.trust-store", trustStoreLocation);
- props.put("server.ssl.trust-store-password", trustStorePassword);
- }
-
- props.put("schema.service.ssl.key-store-password", deobfuscatedKeyStorePassword);
- props.put("schema.service.ssl.trust-store-password", deobfuscatedKeyStorePassword);
-
- String requireClientAuth = System.getenv("REQUIRE_CLIENT_AUTH");
- if (requireClientAuth == null || requireClientAuth.isEmpty()) {
- props.put("server.ssl.client-auth", "need");
- }else {
- props.put("server.ssl.client-auth",requireClientAuth.equals("true")?"need":"want");
- }
-
- new CrudApplication()
- .configure(new SpringApplicationBuilder(CrudApplication.class).properties(props))
- .run(args);
+ public static void main(String[] args) {// NOSONAR
+ String keyStorePassword = System.getProperty("KEY_STORE_PASSWORD");
+ if(keyStorePassword==null || keyStorePassword.isEmpty()){
+ throw new RuntimeException("Env property KEY_STORE_PASSWORD not set");
+ }
+ HashMap<String, Object> props = new HashMap<>();
+ String deobfuscatedKeyStorePassword = keyStorePassword.startsWith("OBF:")?Password.deobfuscate(keyStorePassword):keyStorePassword;
+ props.put("server.ssl.key-store-password", deobfuscatedKeyStorePassword);
+
+ String trustStoreLocation = System.getProperty("TRUST_STORE_LOCATION");
+ String trustStorePassword = System.getProperty("TRUST_STORE_PASSWORD");
+ if(trustStoreLocation!=null && trustStorePassword !=null){
+ trustStorePassword = trustStorePassword.startsWith("OBF:")?Password.deobfuscate(trustStorePassword):trustStorePassword;
+ props.put("server.ssl.trust-store", trustStoreLocation);
+ props.put("server.ssl.trust-store-password", trustStorePassword);
}
- /**
- * Set required trust store system properties using values from application.properties
- */
- @PostConstruct
- public void setSystemProperties() {
- String trustStorePath = env.getProperty("server.ssl.key-store");
- if (trustStorePath != null) {
- String trustStorePassword = env.getProperty("server.ssl.key-store-password");
+ String authLevel = System.getenv("SSL_CLIENT_AUTH");
+ if (authLevel == null || authLevel.isEmpty()) {
+ props.put("server.ssl.client-auth", "need");
+ }else {
+ props.put("server.ssl.client-auth",authLevel);
+ }
+
+
+ props.put("schema.service.ssl.key-store-password", deobfuscatedKeyStorePassword);
+ props.put("schema.service.ssl.trust-store-password", deobfuscatedKeyStorePassword);
- if (trustStorePassword != null) {
- System.setProperty("javax.net.ssl.trustStore", trustStorePath);
- System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
- } else {
- throw new IllegalArgumentException("Env property server.ssl.key-store-password not set");
- }
- }
+ String requireClientAuth = System.getenv("REQUIRE_CLIENT_AUTH");
+ if (requireClientAuth == null || requireClientAuth.isEmpty()) {
+ props.put("server.ssl.client-auth", "need");
+ }else {
+ props.put("server.ssl.client-auth",requireClientAuth.equals("true")?"need":"want");
}
- public static final Contact DEFAULT_CONTACT = new Contact("Amdocs", "http://www.amdocs.com", "noreply@amdocs.com");
- public static final ApiInfo DEFAULT_API_INFO = new ApiInfo("AAI Gizmo Service", "AAI Gizmo Service.",
- "1.0", "urn:tos", DEFAULT_CONTACT, "Apache 2.0", "API license URL", Collections.emptyList());
+ new CrudApplication()
+ .configure(new SpringApplicationBuilder(CrudApplication.class).properties(props))
+ .run(args);
+ }
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2).apiInfo(DEFAULT_API_INFO).select().paths(PathSelectors.any())
- .apis(RequestHandlerSelectors.basePackage("org.onap.crud")).build();
+ /**
+ * Set required trust store system properties using values from application.properties
+ */
+ @PostConstruct
+ public void setSystemProperties() {
+ String trustStorePath = env.getProperty("server.ssl.key-store");
+ if (trustStorePath != null) {
+ String trustStorePassword = env.getProperty("server.ssl.key-store-password");
+
+ if (trustStorePassword != null) {
+ System.setProperty("javax.net.ssl.trustStore", trustStorePath);
+ System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
+ } else {
+ throw new IllegalArgumentException("Env property server.ssl.key-store-password not set");
+ }
}
-
-
+ }
+ public static final Contact DEFAULT_CONTACT = new Contact("Amdocs", "http://www.amdocs.com", "noreply@amdocs.com");
+
+ public static final ApiInfo DEFAULT_API_INFO = new ApiInfo("AAI Gizmo Service", "AAI Gizmo Service.",
+ "1.0", "urn:tos", DEFAULT_CONTACT, "Apache 2.0", "API license URL", Collections.emptyList());
+
+ public Docket api() {
+ return new Docket(DocumentationType.SWAGGER_2).apiInfo(DEFAULT_API_INFO).select().paths(PathSelectors.any())
+ .apis(RequestHandlerSelectors.basePackage("org.onap.crud")).build();
+ }
+
+
}
diff --git a/src/main/java/org/onap/crud/dao/GraphDao.java b/src/main/java/org/onap/crud/dao/GraphDao.java
index 7cb3d4c..867cf56 100644
--- a/src/main/java/org/onap/crud/dao/GraphDao.java
+++ b/src/main/java/org/onap/crud/dao/GraphDao.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.onap.aai.restclient.client.OperationResult;
+import org.onap.crud.dao.champ.ChampBulkPayload;
import org.onap.crud.entity.Edge;
import org.onap.crud.entity.Vertex;
import org.onap.crud.exception.CrudException;
@@ -91,7 +92,7 @@ public interface GraphDao {
* @throws CrudException
*/
public OperationResult getEdge(String id, String type, Map<String, String> queryParams) throws CrudException;
-
+
/**
* Retrieve a collection of {@link Edge} objects with a given type and which
* match a set of supplied filter parameters.
@@ -187,7 +188,7 @@ public interface GraphDao {
public Vertex addVertex(String type, Map<String, Object> properties, String version, String txId) throws CrudException;
public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String version, String txId)
- throws CrudException;
+ throws CrudException;
public Vertex updateVertex(String id, String type, Map<String, Object> properties, String version, String txId) throws CrudException;
@@ -198,6 +199,8 @@ public interface GraphDao {
public void deleteEdge(String id, String txId) throws CrudException;
public Edge getEdge(String id, String txId) throws CrudException;
-
+
public Edge getEdge(String id) throws CrudException;
+
+ public OperationResult bulkOperation(ChampBulkPayload champPayload) throws CrudException;
}
diff --git a/src/main/java/org/onap/crud/dao/champ/ChampBulkOp.java b/src/main/java/org/onap/crud/dao/champ/ChampBulkOp.java
new file mode 100644
index 0000000..9f7fffe
--- /dev/null
+++ b/src/main/java/org/onap/crud/dao/champ/ChampBulkOp.java
@@ -0,0 +1,116 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.crud.dao.champ;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class ChampBulkOp {
+ private static final Gson gson = new GsonBuilder().create();
+
+ private String operation;
+ private String id;
+ private String type;
+ private String label;
+ private String source;
+ private String target;
+ private Map<String, Object> properties;
+
+
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ public static ChampBulkOp fromJson(String jsonString) {
+ return gson.fromJson(jsonString, ChampBulkOp.class);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public Map<String, Object> getProperties() {
+ return properties;
+ }
+
+ public Object getProperty(String key) {
+ return properties.get(key);
+ }
+
+ public void setProperties(Map<String, Object> properties) {
+ this.properties = properties;
+ }
+
+ public void setProperty(String key, String value) {
+ if (properties == null) {
+ properties = new HashMap<String,Object>();
+ }
+
+ properties.put(key, value);
+ }
+
+ public String getOperation() {
+ return operation;
+ }
+
+ public void setOperation(String operation) {
+ this.operation = operation;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getSource() {
+ return source;
+ }
+
+ public void setSource(String source) {
+ this.source = source;
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public void setTarget(String target) {
+ this.target = target;
+ }
+}
diff --git a/src/main/java/org/onap/crud/dao/champ/ChampBulkPayload.java b/src/main/java/org/onap/crud/dao/champ/ChampBulkPayload.java
new file mode 100644
index 0000000..e00bdd2
--- /dev/null
+++ b/src/main/java/org/onap/crud/dao/champ/ChampBulkPayload.java
@@ -0,0 +1,316 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.crud.dao.champ;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.aai.restclient.client.OperationResult;
+import org.onap.crud.dao.GraphDao;
+import org.onap.crud.entity.Edge;
+import org.onap.crud.entity.Vertex;
+import org.onap.crud.exception.CrudException;
+import org.onap.crud.service.BulkPayload;
+import org.onap.crud.service.EdgePayload;
+import org.onap.crud.service.VertexPayload;
+import org.onap.crud.util.CrudServiceUtil;
+import org.onap.schema.OxmModelValidator;
+import org.onap.schema.RelationshipSchemaValidator;
+
+public class ChampBulkPayload {
+
+ public static String ADD_OP = "add";
+ public static String UPDATE_OP = "modify";
+ public static String DELETE_OP = "delete";
+ public static String PATCH_OP = "patch";
+
+ private List<ChampBulkOp> edgeDeleteOps = new ArrayList<ChampBulkOp>();
+ private List<ChampBulkOp> vertexDeleteOps = new ArrayList<ChampBulkOp>();
+ private List<ChampBulkOp> vertexAddModifyOps = new ArrayList<ChampBulkOp>();
+ private List<ChampBulkOp> edgeAddModifyOps = new ArrayList<ChampBulkOp>();
+
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ public static ChampBulkPayload fromJson(String payload) {
+ return gson.fromJson(payload, ChampBulkPayload.class);
+ }
+
+ public List<ChampBulkOp> getEdgeDeleteOps() {
+ return edgeDeleteOps;
+ }
+
+ public void setEdgeDeleteOps(List<ChampBulkOp> ops) {
+ this.edgeDeleteOps = ops;
+ }
+
+ public List<ChampBulkOp> getVertexDeleteOps() {
+ return vertexDeleteOps;
+ }
+
+ public void setVertexDeleteOps(List<ChampBulkOp> ops) {
+ this.vertexDeleteOps = ops;
+ }
+
+ public List<ChampBulkOp> getVertexAddModifyOps() {
+ return vertexAddModifyOps;
+ }
+
+ public void setVertexAddModifyOps(List<ChampBulkOp> ops) {
+ this.vertexAddModifyOps = ops;
+ }
+
+ public List<ChampBulkOp> getEdgeAddModifyOps() {
+ return edgeAddModifyOps;
+ }
+
+ public void setEdgeAddModifyOps(List<ChampBulkOp> ops) {
+ this.edgeAddModifyOps = ops;
+ }
+
+ public void fromGizmoPayload(BulkPayload gizmoPayload, String version, HttpHeaders headers, GraphDao champDao) throws CrudException {
+ edgeDeleteOps = new ArrayList<ChampBulkOp>();
+ vertexDeleteOps = new ArrayList<ChampBulkOp>();
+ vertexAddModifyOps = new ArrayList<ChampBulkOp>();
+ edgeAddModifyOps = new ArrayList<ChampBulkOp>();
+
+ Map<String,String> addedVertexes = new HashMap<String,String>();
+
+ // Step 1. Extract edge deletes
+ for (JsonElement v : gizmoPayload.getRelationships()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+ EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
+ ChampBulkOp champOp = new ChampBulkOp();
+ champOp.setId(edgePayload.getId());
+ champOp.setOperation(DELETE_OP);
+ edgeDeleteOps.add(champOp);
+ }
+ }
+
+ // Step 2: Extract vertex deletes
+ for (JsonElement v : gizmoPayload.getObjects()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+ VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
+ String type = OxmModelValidator.resolveCollectionType(version, vertexPayload.getType());
+ ChampBulkOp champOp = new ChampBulkOp();
+ champOp.setId(vertexPayload.getId());
+ champOp.setOperation(DELETE_OP);
+ champOp.setType(type);
+ vertexDeleteOps.add(champOp);
+ }
+ }
+
+ // Step 3: Extract vertex add/modify
+ for (JsonElement v : gizmoPayload.getObjects()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+ VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ // Add vertex
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
+ vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
+ headers, true));
+ Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, vertexPayload.getType(),
+ vertexPayload.getProperties());
+ validatedVertex.getProperties().put(OxmModelValidator.Metadata.NODE_TYPE.propertyName(), vertexPayload.getType());
+
+ ChampBulkOp champOp = new ChampBulkOp();
+ champOp.setLabel(item.getKey());
+ champOp.setOperation(ADD_OP);
+ champOp.setType(vertexPayload.getType());
+ champOp.setProperties(validatedVertex.getProperties());
+ vertexAddModifyOps.add(champOp);
+ }
+
+ // Update vertex
+ else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
+ vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
+ headers, false));
+ Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(vertexPayload.getId(), version,
+ vertexPayload.getType(), vertexPayload.getProperties());
+ validatedVertex.getProperties().put(OxmModelValidator.Metadata.NODE_TYPE.propertyName(), vertexPayload.getType());
+
+ ChampBulkOp champOp = new ChampBulkOp();
+ champOp.setLabel(item.getKey());
+ champOp.setId(vertexPayload.getId());
+ champOp.setOperation(UPDATE_OP);
+ champOp.setType(vertexPayload.getType());
+ champOp.setProperties(validatedVertex.getProperties());
+ vertexAddModifyOps.add(champOp);
+ }
+
+ // Patch vertex
+ else if (opr.getValue().getAsString().equalsIgnoreCase("patch")) {
+ if ( (vertexPayload.getId() == null) || (vertexPayload.getType() == null) ) {
+ throw new CrudException("id and type must be specified for patch request", Status.BAD_REQUEST);
+ }
+
+ vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
+ headers, false));
+
+ OperationResult existingVertexOpResult =
+ champDao.getVertex(vertexPayload.getId(),
+ OxmModelValidator.resolveCollectionType(version, vertexPayload.getType()),
+ version, new HashMap<String, String>());
+
+ Vertex existingVertex = Vertex.fromJson(existingVertexOpResult.getResult(), version);
+ Vertex validatedVertex = OxmModelValidator.validateIncomingPatchPayload(vertexPayload.getId(),
+ version, vertexPayload.getType(), vertexPayload.getProperties(), existingVertex);
+ validatedVertex.getProperties().put(OxmModelValidator.Metadata.NODE_TYPE.propertyName(), vertexPayload.getType());
+
+ ChampBulkOp champOp = new ChampBulkOp();
+ champOp.setLabel(item.getKey());
+ champOp.setId(vertexPayload.getId());
+ champOp.setOperation(UPDATE_OP);
+ champOp.setType(vertexPayload.getType());
+ champOp.setProperties(validatedVertex.getProperties());
+ vertexAddModifyOps.add(champOp);
+ }
+
+ addedVertexes.put(item.getKey(), "services/inventory/" + version + "/" + vertexPayload.getType()+ "/" + item.getKey());
+ }
+
+ // Step 4: Extract edge add/modify
+ for (JsonElement v : gizmoPayload.getRelationships()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+ EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ // Add/Update edge
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")
+ || opr.getValue().getAsString().equalsIgnoreCase("modify")
+ || opr.getValue().getAsString().equalsIgnoreCase("patch")) {
+
+
+
+
+ ChampBulkOp champOp = new ChampBulkOp();
+ champOp.setLabel(item.getKey());
+
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
+ // If the source/target is a vertex that hasn't been created yet, get the types from the map
+ String sourceUrl = edgePayload.getSource();
+ String targetUrl = edgePayload.getTarget();
+ edgePayload.setSource(resolveUrl(edgePayload.getSource(), addedVertexes));
+ edgePayload.setTarget(resolveUrl(edgePayload.getTarget(), addedVertexes));
+
+ // If the type isn't set, resolve it based on on the source and target vertex types
+ if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
+ edgePayload.setType(CrudServiceUtil.determineEdgeType(edgePayload, version));
+ }
+
+ champOp.setType(edgePayload.getType());
+ Edge validatedEdge = RelationshipSchemaValidator.validateIncomingAddPayload(version, edgePayload.getType(), edgePayload);
+ champOp.setOperation(ADD_OP);
+ champOp.setProperties(validatedEdge.getProperties());
+ champOp.setSource(sourceUrl.substring(sourceUrl.lastIndexOf('/') + 1));
+ champOp.setTarget(targetUrl.substring(targetUrl.lastIndexOf('/') + 1));
+ } else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
+ Edge edge = champDao.getEdge(edgePayload.getId());
+ if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
+ edgePayload.setType(edge.getType());
+ }
+ champOp.setType(edgePayload.getType());
+ Edge validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, edgePayload);
+ champOp.setOperation(UPDATE_OP);
+ champOp.setId(edgePayload.getId());
+ champOp.setProperties(validatedEdge.getProperties());
+ champOp.setSource(edge.getSource().getId().get());
+ champOp.setTarget(edge.getTarget().getId().get());
+ } else {
+ if (edgePayload.getId() == null) {
+ throw new CrudException("id must be specified for patch request", Status.BAD_REQUEST);
+ }
+ Edge existingEdge = champDao.getEdge(edgePayload.getId());
+ if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
+ edgePayload.setType(existingEdge.getType());
+ }
+ champOp.setType(edgePayload.getType());
+ Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(existingEdge, version, edgePayload);
+ champOp.setOperation(UPDATE_OP);
+ champOp.setId(edgePayload.getId());
+ champOp.setProperties(patchedEdge.getProperties());
+ champOp.setSource(existingEdge.getSource().getId().get());
+ champOp.setTarget(existingEdge.getTarget().getId().get());
+ }
+
+ edgeAddModifyOps.add(champOp);
+ }
+ }
+ }
+
+ private String resolveUrl(String vertexUrl, Map<String, String> addedVertexes) throws CrudException {
+ if (vertexUrl.startsWith("$")) {
+ String key = vertexUrl.substring(1);
+ if (addedVertexes.get(key) != null) {
+ return addedVertexes.get(key);
+ }
+
+ throw new CrudException("Unable to resolve vertex " + key, Status.BAD_REQUEST);
+ }
+
+ return vertexUrl;
+ }
+}
diff --git a/src/main/java/org/onap/crud/dao/champ/ChampBulkPayloadResponse.java b/src/main/java/org/onap/crud/dao/champ/ChampBulkPayloadResponse.java
new file mode 100644
index 0000000..3f58c8e
--- /dev/null
+++ b/src/main/java/org/onap/crud/dao/champ/ChampBulkPayloadResponse.java
@@ -0,0 +1,172 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 Amdocs
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.crud.dao.champ;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.onap.crud.entity.Edge;
+import org.onap.crud.entity.Vertex;
+import org.onap.crud.exception.CrudException;
+import org.onap.schema.OxmModelValidator;
+import org.onap.schema.RelationshipSchemaValidator;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+public class ChampBulkPayloadResponse {
+
+ private HashMap<String, Vertex> vertices = new HashMap<>();
+ private HashMap<String, Edge> edges = new HashMap<>();
+
+
+ @Expose
+ @SerializedName(value = "objects")
+ private List<JsonElement> objects = new ArrayList<JsonElement>();
+
+ @Expose
+ @SerializedName(value = "relationships")
+ private List<JsonElement> relationships = new ArrayList<JsonElement>();
+
+
+
+ private static final Gson gson = new GsonBuilder().disableHtmlEscaping().excludeFieldsWithoutExposeAnnotation()
+ .create();
+
+
+ public String toJson() {
+ return gson.toJson(this);
+ }
+
+ public static ChampBulkPayloadResponse fromJson(String payload) {
+ ChampBulkPayloadResponse response = gson.fromJson(payload, ChampBulkPayloadResponse.class);
+ return response;
+ }
+
+
+
+ public void populateChampData(String version) throws CrudException {
+
+ for (JsonElement object : this.getObjects()) {
+
+ JsonObject champObject = object.getAsJsonObject();
+ String itemKey = champObject.get("label").getAsString();
+ JsonObject vertexObject = champObject.get("vertex").getAsJsonObject();
+ Vertex vertex = OxmModelValidator.validateOutgoingPayload(version, buildVertex(vertexObject));
+ this.getVertices().put(itemKey, vertex);
+ }
+
+ for (JsonElement rel : this.getRelationships()) {
+
+ JsonObject champRelationship = rel.getAsJsonObject();
+ String itemKey = champRelationship.get("label").getAsString();
+ JsonObject relObject = champRelationship.get("edge").getAsJsonObject();
+ Edge edge = RelationshipSchemaValidator.validateOutgoingPayload(version, buildEdge(relObject));
+ this.getEdges().put(itemKey, edge);
+
+ }
+
+
+ }
+
+
+ private Edge buildEdge(JsonObject obj) {
+ JsonObject relKeyObject = obj.get("key").getAsJsonObject();
+
+ String relType = obj.get("type").getAsString();
+ String relKey = relKeyObject.get("value").getAsString();
+
+ Vertex source = buildVertex(obj.get("source").getAsJsonObject());
+ Vertex target = buildVertex(obj.get("target").getAsJsonObject());
+
+ Edge.Builder edgeBuilder = new Edge.Builder(relType).id(relKey).source(source)
+ .target(target);
+
+ if (obj.has("properties")) {
+ JsonObject propsObject = obj.get("properties").getAsJsonObject();
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ propsObject.getAsJsonObject().entrySet());
+
+ for (Map.Entry<String, JsonElement> entry :entries) {
+ edgeBuilder.property(entry.getKey(), entry.getValue().getAsString());
+ }
+
+ }
+
+ return edgeBuilder.build();
+ }
+
+ private Vertex buildVertex(JsonObject obj) {
+ JsonObject vertexKeyObject = obj.get("key").getAsJsonObject();
+
+ String vertexType = obj.get("type").getAsString();
+ String vertexKey = vertexKeyObject.get("value").getAsString();
+ Vertex.Builder vertexBuilder = new Vertex.Builder(vertexType).id(vertexKey);
+
+ if (obj.has("properties")) {
+ JsonObject propsObject = obj.get("properties").getAsJsonObject();
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ propsObject.getAsJsonObject().entrySet());
+
+ for (Map.Entry<String, JsonElement> entry :entries) {
+ vertexBuilder.property(entry.getKey(), entry.getValue().getAsString());
+ }
+
+ }
+
+ return vertexBuilder.build();
+ }
+
+ public HashMap<String, Edge> getEdges() {
+ return edges;
+ }
+
+ public void setEdges(HashMap<String, Edge> edges) {
+ this.edges = edges;
+ }
+
+ public List<JsonElement> getObjects() {
+ return objects;
+ }
+
+ public void setObjects(List<JsonElement> objects) {
+ this.objects = objects;
+ }
+
+ public HashMap<String, Vertex> getVertices() {
+ return vertices;
+ }
+
+ public List<JsonElement> getRelationships() {
+ return relationships;
+ }
+
+
+
+
+}
diff --git a/src/main/java/org/onap/crud/dao/champ/ChampDao.java b/src/main/java/org/onap/crud/dao/champ/ChampDao.java
index 554b9fa..402d2cf 100644
--- a/src/main/java/org/onap/crud/dao/champ/ChampDao.java
+++ b/src/main/java/org/onap/crud/dao/champ/ChampDao.java
@@ -54,6 +54,7 @@ public class ChampDao implements GraphDao {
protected String baseObjectUrl;
protected String baseRelationshipUrl;
protected String baseTransactionUrl;
+ protected String baseBulkUrl;
protected static final String HEADER_FROM_APP = "X-FromAppId";
protected static final String HEADER_TRANS_ID = "X-TransactionId";
@@ -61,13 +62,14 @@ public class ChampDao implements GraphDao {
protected static final String OBJECT_SUB_URL = "objects";
protected static final String RELATIONSHIP_SUB_URL = "relationships";
protected static final String TRANSACTION_SUB_URL = "transaction";
+ protected static final String BULK_SUB_URL = "bulk";
// We use a custom vertex serializer for champ because it expects "key"
// instead of "id"
protected static final Gson champGson = new GsonBuilder()
- .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory())
- .registerTypeAdapter(Vertex.class, new ChampVertexSerializer())
- .registerTypeAdapter(Edge.class, new ChampEdgeSerializer()).create();
+ .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory())
+ .registerTypeAdapter(Vertex.class, new ChampVertexSerializer())
+ .registerTypeAdapter(Edge.class, new ChampEdgeSerializer()).create();
public ChampDao() {
}
@@ -76,12 +78,13 @@ public class ChampDao implements GraphDao {
try {
String deobfuscatedCertPassword = certPassword.startsWith("OBF:")?Password.deobfuscate(certPassword):certPassword;
client = new RestClient().authenticationMode(RestAuthenticationMode.SSL_CERT).validateServerHostname(false)
- .validateServerCertChain(false).clientCertFile(CrudServiceConstants.CRD_CHAMP_AUTH_FILE)
- .clientCertPassword(deobfuscatedCertPassword);
+ .validateServerCertChain(false).clientCertFile(CrudServiceConstants.CRD_CHAMP_AUTH_FILE)
+ .clientCertPassword(deobfuscatedCertPassword);
baseObjectUrl = champUrl + OBJECT_SUB_URL;
baseRelationshipUrl = champUrl + RELATIONSHIP_SUB_URL;
baseTransactionUrl = champUrl + TRANSACTION_SUB_URL;
+ baseBulkUrl = champUrl + BULK_SUB_URL;
} catch (Exception e) {
System.out.println("Error setting up Champ configuration");
e.printStackTrace();
@@ -90,10 +93,10 @@ public class ChampDao implements GraphDao {
}
public ChampDao(RestClient client, String baseObjectUrl, String baseRelationshipUrl, String baseTransactionUrl) {
- this.client = client;
- this.baseObjectUrl = baseObjectUrl;
- this.baseRelationshipUrl = baseRelationshipUrl;
- this.baseTransactionUrl = baseTransactionUrl;
+ this.client = client;
+ this.baseObjectUrl = baseObjectUrl;
+ this.baseRelationshipUrl = baseRelationshipUrl;
+ this.baseTransactionUrl = baseTransactionUrl;
}
@Override
@@ -117,8 +120,8 @@ public class ChampDao implements GraphDao {
strBuild.append(id);
if(queryParams != null && !queryParams.isEmpty())
{
- strBuild.append("?");
- strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset()));
+ strBuild.append("?");
+ strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset()));
}
OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE);
@@ -130,50 +133,50 @@ public class ChampDao implements GraphDao {
// We didn't find a vertex with the supplied type, so just throw an
// exception.
throw new CrudException("No vertex with id " + id + " and type " + type + " found in graph",
- javax.ws.rs.core.Response.Status.NOT_FOUND);
+ javax.ws.rs.core.Response.Status.NOT_FOUND);
}
return getResult;
} else {
// We didn't find a vertex with the supplied id, so just throw an
// exception.
- throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph");
+ throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph");
}
}
@Override
public List<Edge> getVertexEdges(String id, Map<String, String> queryParams, String txId) throws CrudException {
- StringBuilder strBuild = new StringBuilder(baseObjectUrl);
- strBuild.append("/relationships/");
- strBuild.append(id);
+ StringBuilder strBuild = new StringBuilder(baseObjectUrl);
+ strBuild.append("/relationships/");
+ strBuild.append(id);
- Map<String,String> queryParamsCopy = null;
- if (queryParams != null) {
- queryParamsCopy = new HashMap<String,String>(queryParams);
- }
- else {
- queryParamsCopy = new HashMap<String,String>();
- }
+ Map<String,String> queryParamsCopy = null;
+ if (queryParams != null) {
+ queryParamsCopy = new HashMap<String,String>(queryParams);
+ }
+ else {
+ queryParamsCopy = new HashMap<String,String>();
+ }
- if (txId != null) {
- queryParamsCopy.put("transactionId", txId);
- }
+ if (txId != null) {
+ queryParamsCopy.put("transactionId", txId);
+ }
- if (!queryParamsCopy.isEmpty())
- {
- strBuild.append("?");
- strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParamsCopy), Charset.defaultCharset()));
- }
+ if (!queryParamsCopy.isEmpty())
+ {
+ strBuild.append("?");
+ strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParamsCopy), Charset.defaultCharset()));
+ }
- OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE);
+ OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE);
- if (getResult.getResultCode() == 200) {
- return champGson.fromJson(getResult.getResult(), new TypeToken<List<Edge>>() {
- }.getType());
- } else {
- // We didn't find a vertex with the supplied id, so just throw an
- // exception.
- throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph");
- }
+ if (getResult.getResultCode() == 200) {
+ return champGson.fromJson(getResult.getResult(), new TypeToken<List<Edge>>() {
+ }.getType());
+ } else {
+ // We didn't find a vertex with the supplied id, so just throw an
+ // exception.
+ throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph");
+ }
}
@Override
@@ -188,7 +191,7 @@ public class ChampDao implements GraphDao {
List<NameValuePair> queryParams = convertToNameValuePair(filter);
queryParams.addAll(convertToNameValuePair("properties", properties));
String url = baseObjectUrl + "/filter" + "?"
- + URLEncodedUtils.format(queryParams, Charset.defaultCharset());
+ + URLEncodedUtils.format(queryParams, Charset.defaultCharset());
OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
@@ -208,8 +211,8 @@ public class ChampDao implements GraphDao {
strBuild.append(id);
if(queryParams != null && !queryParams.isEmpty())
{
- strBuild.append("?");
- strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset()));
+ strBuild.append("?");
+ strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset()));
}
OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE);
@@ -220,7 +223,7 @@ public class ChampDao implements GraphDao {
// We didn't find an edge with the supplied type, so just throw an
// exception.
throw new CrudException("No edge with id " + id + " and type " + type + " found in graph",
- javax.ws.rs.core.Response.Status.NOT_FOUND);
+ javax.ws.rs.core.Response.Status.NOT_FOUND);
}
return getResult;
} else {
@@ -233,12 +236,12 @@ public class ChampDao implements GraphDao {
@Override
public OperationResult getEdges(String type, Map<String, Object> filter) throws CrudException {
String url = baseRelationshipUrl + "/filter" + "?"
- + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset());
+ + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset());
OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == 200) {
- return getResult;
+ return getResult;
} else {
// We didn't find a vertex with the supplied id, so just throw an
// exception.
@@ -259,7 +262,7 @@ public class ChampDao implements GraphDao {
Vertex insertVertex = insertVertexBuilder.build();
OperationResult getResult = client.post(url, insertVertex.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
+ MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
return getResult;
@@ -285,7 +288,7 @@ public class ChampDao implements GraphDao {
String payload = insertVertex.toJson(champGson);
OperationResult getResult = client.put(url, payload, createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
+ MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
return getResult;
@@ -324,7 +327,7 @@ public class ChampDao implements GraphDao {
String edgeJson = insertEdge.toJson(champGson);
OperationResult getResult = client.post(url, edgeJson, createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
+ MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
return getResult;
@@ -344,7 +347,7 @@ public class ChampDao implements GraphDao {
String edgeJson = edge.toJson(champGson);
OperationResult getResult = client.put(url, edgeJson, createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
+ MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
return getResult;
@@ -385,11 +388,11 @@ public class ChampDao implements GraphDao {
String url = baseTransactionUrl + "/" + id;
OperationResult getResult = client.put(url, "{\"method\": \"commit\"}", createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.TEXT_PLAIN_TYPE);
+ MediaType.TEXT_PLAIN_TYPE);
if (getResult.getResultCode() != 200) {
throw new CrudException("Unable to commit transaction",
- Response.Status.fromStatusCode(getResult.getResultCode()));
+ Response.Status.fromStatusCode(getResult.getResultCode()));
}
}
@@ -398,11 +401,11 @@ public class ChampDao implements GraphDao {
String url = baseTransactionUrl + "/" + id;
OperationResult getResult = client.put(url, "{\"method\": \"rollback\"}", createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.TEXT_PLAIN_TYPE);
+ MediaType.TEXT_PLAIN_TYPE);
if (getResult.getResultCode() != 200) {
throw new CrudException("Unable to rollback transaction",
- Response.Status.fromStatusCode(getResult.getResultCode()));
+ Response.Status.fromStatusCode(getResult.getResultCode()));
}
}
@@ -431,7 +434,7 @@ public class ChampDao implements GraphDao {
Vertex insertVertex = insertVertexBuilder.build();
OperationResult getResult = client.post(url, insertVertex.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
+ MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
return Vertex.fromJson(getResult.getResult(), version);
@@ -444,7 +447,7 @@ public class ChampDao implements GraphDao {
@Override
public Edge addEdge(String type, Vertex source, Vertex target, Map<String, Object> properties, String version, String txId)
- throws CrudException {
+ throws CrudException {
String url = baseRelationshipUrl + "?transactionId=" + txId;
// Try requests to ensure source and target exist in Champ
@@ -456,7 +459,7 @@ public class ChampDao implements GraphDao {
Edge insertEdge = insertEdgeBuilder.build();
OperationResult getResult = client.post(url, insertEdge.toJson(champGson), createHeader(),
- MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
+ MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) {
return Edge.fromJson(getResult.getResult());
@@ -482,7 +485,7 @@ public class ChampDao implements GraphDao {
String payload = insertVertex.toJson(champGson);
OperationResult getResult = client.put(url, payload, createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
+ MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
return Vertex.fromJson(getResult.getResult(), version);
@@ -512,7 +515,7 @@ public class ChampDao implements GraphDao {
}
String url = baseRelationshipUrl + "/" + edge.getId().get() + "?transactionId=" + txId;
OperationResult getResult = client.put(url, edge.toJson(champGson), createHeader(), MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_JSON_TYPE);
+ MediaType.APPLICATION_JSON_TYPE);
if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
return Edge.fromJson(getResult.getResult());
@@ -520,7 +523,7 @@ public class ChampDao implements GraphDao {
// We didn't create an edge with the supplied type, so just throw an
// exception.
throw new CrudException("Failed to update edge: " + getResult.getFailureCause(),
- Response.Status.fromStatusCode(getResult.getResultCode()));
+ Response.Status.fromStatusCode(getResult.getResultCode()));
}
}
@@ -576,7 +579,7 @@ public class ChampDao implements GraphDao {
// We didn't find a vertex with the supplied type, so just throw an
// exception.
throw new CrudException("No vertex with id " + id + " and type " + type + " found in graph",
- javax.ws.rs.core.Response.Status.NOT_FOUND);
+ javax.ws.rs.core.Response.Status.NOT_FOUND);
}
return vert;
} else {
@@ -613,12 +616,26 @@ public class ChampDao implements GraphDao {
private CrudException createErrorException(OperationResult result, javax.ws.rs.core.Response.Status defaultErrorCode , String defaultErrorMsg)
{
- CrudException ce = null;
- if(result != null)
- ce = new CrudException(result.getFailureCause(), Response.Status.fromStatusCode(result.getResultCode()));
- else
- ce = new CrudException(defaultErrorMsg, defaultErrorCode);
- return ce;
+ CrudException ce = null;
+ if(result != null)
+ ce = new CrudException(result.getFailureCause(), Response.Status.fromStatusCode(result.getResultCode()));
+ else
+ ce = new CrudException(defaultErrorMsg, defaultErrorCode);
+ return ce;
+ }
+
+ @Override
+ public OperationResult bulkOperation(ChampBulkPayload champPayload) throws CrudException {
+ String url = baseBulkUrl;
+
+ OperationResult getResult = client.post(url, champPayload.toJson(), createHeader(), MediaType.APPLICATION_JSON_TYPE,
+ MediaType.APPLICATION_JSON_TYPE);
+
+ if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) {
+ return getResult;
+ } else {
+ throw new CrudException("Bulk request failed: " + getResult.getFailureCause(), Response.Status.fromStatusCode(getResult.getResultCode()));
+ }
}
}
diff --git a/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java b/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java
index 2b669ae..ed0ff24 100644
--- a/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java
+++ b/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java
@@ -94,6 +94,14 @@ public enum CrudServiceMsgs implements LogMessageEnum {
ASYNC_DATA_SERVICE_ERROR,
/**
+ * Any info log related to CHAMP_BULK_OP_INFO
+ *
+ * <p>Arguments:
+ * {0} - Info.
+ */
+ CHAMP_BULK_OP_INFO,
+
+ /**
* Any info log related to ASYNC_DATA_CACHE_INFO
*
* <p>Arguments:
diff --git a/src/main/java/org/onap/crud/service/AbstractGraphDataService.java b/src/main/java/org/onap/crud/service/AbstractGraphDataService.java
index 8225adf..1fdd841 100644
--- a/src/main/java/org/onap/crud/service/AbstractGraphDataService.java
+++ b/src/main/java/org/onap/crud/service/AbstractGraphDataService.java
@@ -22,16 +22,12 @@ package org.onap.crud.service;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response.Status;
import net.dongliu.gson.GsonJava8TypeAdapterFactory;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.onap.aai.restclient.client.OperationResult;
@@ -92,199 +88,6 @@ public abstract class AbstractGraphDataService {
return new ImmutablePair<>(entityTag, CrudResponseBuilder.buildGetVerticesResponse(vertices, version));
}
- public String addBulk(String version, BulkPayload payload, HttpHeaders headers) throws CrudException {
- HashMap<String, Vertex> vertices = new HashMap<>();
- HashMap<String, Edge> edges = new HashMap<>();
-
- String txId = dao.openTransaction();
-
- try {
- // Step 1. Handle edge deletes (must happen before vertex deletes)
- for (JsonElement v : payload.getRelationships()) {
- List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
- v.getAsJsonObject().entrySet());
-
- if (entries.size() != 2) {
- throw new CrudException("", Status.BAD_REQUEST);
- }
- Map.Entry<String, JsonElement> opr = entries.get(0);
- Map.Entry<String, JsonElement> item = entries.get(1);
- EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
-
- if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
- deleteBulkEdge(edgePayload.getId(), version, txId);
- }
- }
-
- // Step 2: Handle vertex deletes
- for (JsonElement v : payload.getObjects()) {
- List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
- v.getAsJsonObject().entrySet());
-
- if (entries.size() != 2) {
- throw new CrudException("", Status.BAD_REQUEST);
- }
-
- Map.Entry<String, JsonElement> opr = entries.get(0);
- Map.Entry<String, JsonElement> item = entries.get(1);
- VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
-
- if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
- String type = OxmModelValidator.resolveCollectionType(version, vertexPayload.getType());
- deleteBulkVertex(vertexPayload.getId(), version, type, txId);
- }
- }
-
- // Step 3: Handle vertex add/modify (must happen before edge adds)
- for (JsonElement v : payload.getObjects()) {
- List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
- v.getAsJsonObject().entrySet());
-
- if (entries.size() != 2) {
- throw new CrudException("", Status.BAD_REQUEST);
- }
- Map.Entry<String, JsonElement> opr = entries.get(0);
- Map.Entry<String, JsonElement> item = entries.get(1);
- VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
-
- // Add vertex
- if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
- vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
- headers, true));
- Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, vertexPayload.getType(),
- vertexPayload.getProperties());
- Vertex persistedVertex = addBulkVertex(validatedVertex, version, txId);
- Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
- vertices.put(item.getKey(), outgoingVertex);
- }
-
- // Update vertex
- else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
- vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
- headers, false));
- Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(vertexPayload.getId(), version,
- vertexPayload.getType(), vertexPayload.getProperties());
- Vertex persistedVertex = updateBulkVertex(validatedVertex, vertexPayload.getId(), version, txId);
- Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
- vertices.put(item.getKey(), outgoingVertex);
- }
-
- // Patch vertex
- else if (opr.getValue().getAsString().equalsIgnoreCase("patch")) {
- if ( (vertexPayload.getId() == null) || (vertexPayload.getType() == null) ) {
- throw new CrudException("id and type must be specified for patch request", Status.BAD_REQUEST);
- }
-
- vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
- headers, false));
-
- OperationResult existingVertexOpResult = dao.getVertex(vertexPayload.getId(), OxmModelValidator.resolveCollectionType(version, vertexPayload.getType()), version, new HashMap<String, String>());
- Vertex existingVertex = Vertex.fromJson(existingVertexOpResult.getResult(), version);
- Vertex validatedVertex = OxmModelValidator.validateIncomingPatchPayload(vertexPayload.getId(),
- version, vertexPayload.getType(), vertexPayload.getProperties(), existingVertex);
- Vertex persistedVertex = updateBulkVertex(validatedVertex, vertexPayload.getId(), version, txId);
- Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
- vertices.put(item.getKey(), outgoingVertex);
- }
- }
-
- // Step 4: Handle edge add/modify
- for (JsonElement v : payload.getRelationships()) {
- List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
- v.getAsJsonObject().entrySet());
-
- if (entries.size() != 2) {
- throw new CrudException("", Status.BAD_REQUEST);
- }
- Map.Entry<String, JsonElement> opr = entries.get(0);
- Map.Entry<String, JsonElement> item = entries.get(1);
- EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
-
- // Add/Update edge
- if (opr.getValue().getAsString().equalsIgnoreCase("add")
- || opr.getValue().getAsString().equalsIgnoreCase("modify")
- || opr.getValue().getAsString().equalsIgnoreCase("patch")) {
- Edge validatedEdge;
- Edge persistedEdge;
- if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
- // Fix the source/destination
- if (edgePayload.getSource().startsWith("$")) {
- Vertex source = vertices.get(edgePayload.getSource().substring(1));
- if (source == null) {
- throw new CrudException("Not able to find vertex: " + edgePayload.getSource().substring(1),
- Status.INTERNAL_SERVER_ERROR);
- }
- edgePayload
- .setSource("services/inventory/" + version + "/" + source.getType() + "/" + source.getId().get());
- }
- if (edgePayload.getTarget().startsWith("$")) {
- Vertex target = vertices.get(edgePayload.getTarget().substring(1));
- if (target == null) {
- throw new CrudException("Not able to find vertex: " + edgePayload.getTarget().substring(1),
- Status.INTERNAL_SERVER_ERROR);
- }
- edgePayload
- .setTarget("services/inventory/" + version + "/" + target.getType() + "/" + target.getId().get());
- }
-
- // If the type isn't set, resolve it based on on the sourece and target vertex types
- if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
- edgePayload.setType(CrudServiceUtil.determineEdgeType(edgePayload, version));
- }
-
- validatedEdge = RelationshipSchemaValidator.validateIncomingAddPayload(version, edgePayload.getType(),edgePayload);
-
- persistedEdge = addBulkEdge(validatedEdge, version, txId);
- } else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
- Edge edge = dao.getEdge(edgePayload.getId(), txId);
-
- // If the type isn't set, resolve it based on on the sourece and target vertex types
- if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
- edgePayload.setType(edge.getType());
- }
-
- validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, edgePayload);
-
- persistedEdge = updateBulkEdge(validatedEdge, version, txId);
- } else {
- if (edgePayload.getId() == null) {
- throw new CrudException("id must be specified for patch request", Status.BAD_REQUEST);
- }
- Edge existingEdge = dao.getEdge(edgePayload.getId(), txId);
-
- // If the type isn't set, resolve it based on on the sourece and target vertex types
- if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
- edgePayload.setType(existingEdge.getType());
- }
-
- Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(existingEdge, version, edgePayload);
- persistedEdge = updateBulkEdge(patchedEdge, version, txId);
- }
-
-
- Edge outgoingEdge = RelationshipSchemaValidator.validateOutgoingPayload(version, persistedEdge);
- edges.put(item.getKey(), outgoingEdge);
- }
- }
-
- // commit transaction
- dao.commitTransaction(txId);
- } catch (CrudException ex) {
- dao.rollbackTransaction(txId);
- throw ex;
- } catch (Exception ex) {
- dao.rollbackTransaction(txId);
- throw ex;
- } finally {
- if (dao.transactionExists(txId)) {
- dao.rollbackTransaction(txId);
- }
- }
-
- return CrudResponseBuilder.buildUpsertBulkResponse(vertices, edges, version, payload);
- }
-
-
public abstract ImmutablePair<EntityTag, String> addVertex(String version, String type, VertexPayload payload)
throws CrudException;
public abstract ImmutablePair<EntityTag, String> updateVertex(String version, String id, String type,
@@ -299,13 +102,7 @@ public abstract class AbstractGraphDataService {
EdgePayload payload) throws CrudException;
public abstract ImmutablePair<EntityTag, String> patchEdge(String version, String id, String type,
EdgePayload payload) throws CrudException;
-
- protected abstract Vertex addBulkVertex(Vertex vertex, String version, String dbTransId) throws CrudException;
- protected abstract Vertex updateBulkVertex(Vertex vertex, String id, String version, String dbTransId) throws CrudException;
- protected abstract void deleteBulkVertex(String id, String version, String type, String dbTransId) throws CrudException;
-
- protected abstract Edge addBulkEdge(Edge edge, String version, String dbTransId) throws CrudException;
- protected abstract Edge updateBulkEdge(Edge edge, String version, String dbTransId) throws CrudException;
- protected abstract void deleteBulkEdge(String id, String version, String dbTransId) throws CrudException;
+
+ public abstract String addBulk(String version, BulkPayload payload, HttpHeaders headers) throws CrudException;
}
diff --git a/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java b/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java
index 14ba7f2..7906de0 100644
--- a/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java
+++ b/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java
@@ -23,7 +23,10 @@ package org.onap.crud.service;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Timer;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -35,6 +38,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.PreDestroy;
import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.onap.aai.cl.api.LogFields;
@@ -56,12 +60,16 @@ import org.onap.crud.event.envelope.GraphEventEnvelope;
import org.onap.crud.event.response.GraphEventResponseHandler;
import org.onap.crud.exception.CrudException;
import org.onap.crud.logging.CrudServiceMsgs;
+import org.onap.crud.parser.CrudResponseBuilder;
import org.onap.crud.util.CrudProperties;
import org.onap.crud.util.CrudServiceConstants;
+import org.onap.crud.util.CrudServiceUtil;
import org.onap.crud.util.etag.EtagGenerator;
import org.onap.schema.OxmModelValidator;
import org.onap.schema.RelationshipSchemaValidator;
+import com.google.gson.JsonElement;
+
public class CrudAsyncGraphDataService extends AbstractGraphDataService {
private static Integer requestTimeOut;
@@ -119,8 +127,8 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService {
// Start the Response Consumer timer
CrudAsyncResponseConsumer crudAsyncResponseConsumer = new CrudAsyncResponseConsumer(
- asyncResponseConsumer, new GraphEventUpdater()
- );
+ asyncResponseConsumer, new GraphEventUpdater()
+ );
timer = new Timer("crudAsyncResponseConsumer-1");
timer.schedule(crudAsyncResponseConsumer, responsePollInterval, responsePollInterval);
@@ -178,8 +186,8 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService {
logger.info(CrudServiceMsgs.ASYNC_DATA_SERVICE_INFO,
"Event submitted of type: " + event.getObjectType() + " with key: " + event.getObjectKey()
- + " , transaction-id: " + event.getTransactionId() + " , operation: "
- + event.getOperation().toString());
+ + " , transaction-id: " + event.getTransactionId() + " , operation: "
+ + event.getOperation().toString());
ExecutorService executor =
Executors.newSingleThreadExecutor(new CrudThreadFactory("TX-" + event.getTransactionId()));
@@ -367,8 +375,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService {
timer.cancel();
}
- @Override
- protected Vertex addBulkVertex(Vertex vertex, String version, String dbTransId) throws CrudException {
+ private Vertex addBulkVertex(Vertex vertex, String version, String dbTransId) throws CrudException {
GraphEvent event = GraphEvent.builder(GraphEventOperation.CREATE)
.vertex(GraphEventVertex.fromVertex(vertex, version)).build();
event.setDbTransactionId(dbTransId);
@@ -376,8 +383,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService {
return response.getVertex().toVertex();
}
- @Override
- protected Vertex updateBulkVertex(Vertex vertex, String id, String version, String dbTransId) throws CrudException {
+ private Vertex updateBulkVertex(Vertex vertex, String id, String version, String dbTransId) throws CrudException {
GraphEvent event = GraphEvent.builder(GraphEventOperation.UPDATE)
.vertex(GraphEventVertex.fromVertex(vertex, version)).build();
event.setDbTransactionId(dbTransId);
@@ -385,16 +391,14 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService {
return response.getVertex().toVertex();
}
- @Override
- protected void deleteBulkVertex(String id, String version, String type, String dbTransId) throws CrudException {
+ private void deleteBulkVertex(String id, String version, String type, String dbTransId) throws CrudException {
GraphEvent event = GraphEvent.builder(GraphEventOperation.DELETE)
.vertex(new GraphEventVertex(id, version, type, null)).build();
event.setDbTransactionId(dbTransId);
publishEvent(event);
}
- @Override
- protected Edge addBulkEdge(Edge edge, String version, String dbTransId) throws CrudException {
+ private Edge addBulkEdge(Edge edge, String version, String dbTransId) throws CrudException {
GraphEvent event =
GraphEvent.builder(GraphEventOperation.CREATE).edge(GraphEventEdge.fromEdge(edge, version)).build();
event.setDbTransactionId(dbTransId);
@@ -402,8 +406,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService {
return response.getEdge().toEdge();
}
- @Override
- protected Edge updateBulkEdge(Edge edge, String version, String dbTransId) throws CrudException {
+ private Edge updateBulkEdge(Edge edge, String version, String dbTransId) throws CrudException {
GraphEvent event =
GraphEvent.builder(GraphEventOperation.UPDATE).edge(GraphEventEdge.fromEdge(edge, version)).build();
event.setDbTransactionId(dbTransId);
@@ -411,8 +414,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService {
return response.getEdge().toEdge();
}
- @Override
- protected void deleteBulkEdge(String id, String version, String dbTransId) throws CrudException {
+ private void deleteBulkEdge(String id, String version, String dbTransId) throws CrudException {
// Get the edge type
String type = null;
try {
@@ -423,13 +425,204 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService {
// Likely the client is trying to delete an edge which isn't present. Just swallow the exception
// and let the bulk request fail via the normal path.
}
-
+
GraphEvent event = GraphEvent.builder(GraphEventOperation.DELETE)
.edge(new GraphEventEdge(id, version, type, null, null, null)).build();
event.setDbTransactionId(dbTransId);
publishEvent(event);
}
+ @Override
+ public String addBulk(String version, BulkPayload payload, HttpHeaders headers) throws CrudException {
+ HashMap<String, Vertex> vertices = new HashMap<>();
+ HashMap<String, Edge> edges = new HashMap<>();
+
+ String txId = dao.openTransaction();
+
+ try {
+ // Step 1. Handle edge deletes (must happen before vertex deletes)
+ for (JsonElement v : payload.getRelationships()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+ EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
+ deleteBulkEdge(edgePayload.getId(), version, txId);
+ }
+ }
+
+ // Step 2: Handle vertex deletes
+ for (JsonElement v : payload.getObjects()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+ VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ if (opr.getValue().getAsString().equalsIgnoreCase("delete")) {
+ String type = OxmModelValidator.resolveCollectionType(version, vertexPayload.getType());
+ deleteBulkVertex(vertexPayload.getId(), version, type, txId);
+ }
+ }
+
+ // Step 3: Handle vertex add/modify (must happen before edge adds)
+ for (JsonElement v : payload.getObjects()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+ VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ // Add vertex
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
+ vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
+ headers, true));
+ Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, vertexPayload.getType(),
+ vertexPayload.getProperties());
+ Vertex persistedVertex = addBulkVertex(validatedVertex, version, txId);
+ Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
+ vertices.put(item.getKey(), outgoingVertex);
+ }
+
+ // Update vertex
+ else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
+ vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
+ headers, false));
+ Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(vertexPayload.getId(), version,
+ vertexPayload.getType(), vertexPayload.getProperties());
+ Vertex persistedVertex = updateBulkVertex(validatedVertex, vertexPayload.getId(), version, txId);
+ Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
+ vertices.put(item.getKey(), outgoingVertex);
+ }
+
+ // Patch vertex
+ else if (opr.getValue().getAsString().equalsIgnoreCase("patch")) {
+ if ( (vertexPayload.getId() == null) || (vertexPayload.getType() == null) ) {
+ throw new CrudException("id and type must be specified for patch request", Status.BAD_REQUEST);
+ }
+
+ vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(),
+ headers, false));
+
+ OperationResult existingVertexOpResult = dao.getVertex(vertexPayload.getId(), OxmModelValidator.resolveCollectionType(version, vertexPayload.getType()), version, new HashMap<String, String>());
+ Vertex existingVertex = Vertex.fromJson(existingVertexOpResult.getResult(), version);
+ Vertex validatedVertex = OxmModelValidator.validateIncomingPatchPayload(vertexPayload.getId(),
+ version, vertexPayload.getType(), vertexPayload.getProperties(), existingVertex);
+ Vertex persistedVertex = updateBulkVertex(validatedVertex, vertexPayload.getId(), version, txId);
+ Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex);
+ vertices.put(item.getKey(), outgoingVertex);
+ }
+ }
+
+ // Step 4: Handle edge add/modify
+ for (JsonElement v : payload.getRelationships()) {
+ List<Map.Entry<String, JsonElement>> entries = new ArrayList<Map.Entry<String, JsonElement>>(
+ v.getAsJsonObject().entrySet());
+
+ if (entries.size() != 2) {
+ throw new CrudException("", Status.BAD_REQUEST);
+ }
+ Map.Entry<String, JsonElement> opr = entries.get(0);
+ Map.Entry<String, JsonElement> item = entries.get(1);
+ EdgePayload edgePayload = EdgePayload.fromJson(item.getValue().getAsJsonObject().toString());
+
+ // Add/Update edge
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")
+ || opr.getValue().getAsString().equalsIgnoreCase("modify")
+ || opr.getValue().getAsString().equalsIgnoreCase("patch")) {
+ Edge validatedEdge;
+ Edge persistedEdge;
+ if (opr.getValue().getAsString().equalsIgnoreCase("add")) {
+ // Fix the source/destination
+ if (edgePayload.getSource().startsWith("$")) {
+ Vertex source = vertices.get(edgePayload.getSource().substring(1));
+ if (source == null) {
+ throw new CrudException("Not able to find vertex: " + edgePayload.getSource().substring(1),
+ Status.INTERNAL_SERVER_ERROR);
+ }
+ edgePayload
+ .setSource("services/inventory/" + version + "/" + source.getType() + "/" + source.getId().get());
+ }
+ if (edgePayload.getTarget().startsWith("$")) {
+ Vertex target = vertices.get(edgePayload.getTarget().substring(1));
+ if (target == null) {
+ throw new CrudException("Not able to find vertex: " + edgePayload.getTarget().substring(1),
+ Status.INTERNAL_SERVER_ERROR);
+ }
+ edgePayload
+ .setTarget("services/inventory/" + version + "/" + target.getType() + "/" + target.getId().get());
+ }
+
+ // If the type isn't set, resolve it based on on the sourece and target vertex types
+ if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
+ edgePayload.setType(CrudServiceUtil.determineEdgeType(edgePayload, version));
+ }
+
+ validatedEdge = RelationshipSchemaValidator.validateIncomingAddPayload(version, edgePayload.getType(),edgePayload);
+ persistedEdge = addBulkEdge(validatedEdge, version, txId);
+ } else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) {
+ Edge edge = dao.getEdge(edgePayload.getId(), txId);
+
+ // If the type isn't set, resolve it based on on the sourece and target vertex types
+ if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
+ edgePayload.setType(edge.getType());
+ }
+
+ validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, edgePayload);
+ persistedEdge = updateBulkEdge(validatedEdge, version, txId);
+ } else {
+ if (edgePayload.getId() == null) {
+ throw new CrudException("id must be specified for patch request", Status.BAD_REQUEST);
+ }
+ Edge existingEdge = dao.getEdge(edgePayload.getId(), txId);
+
+ // If the type isn't set, resolve it based on on the sourece and target vertex types
+ if (edgePayload.getType() == null || edgePayload.getType().isEmpty()) {
+ edgePayload.setType(existingEdge.getType());
+ }
+
+ Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(existingEdge, version, edgePayload);
+ persistedEdge = updateBulkEdge(patchedEdge, version, txId);
+ }
+
+
+ Edge outgoingEdge = RelationshipSchemaValidator.validateOutgoingPayload(version, persistedEdge);
+ edges.put(item.getKey(), outgoingEdge);
+ }
+ }
+
+ // commit transaction
+ dao.commitTransaction(txId);
+ } catch (CrudException ex) {
+ dao.rollbackTransaction(txId);
+ throw ex;
+ } catch (Exception ex) {
+ dao.rollbackTransaction(txId);
+ throw ex;
+ } finally {
+ if (dao.transactionExists(txId)) {
+ dao.rollbackTransaction(txId);
+ }
+ }
+
+ return CrudResponseBuilder.buildUpsertBulkResponse(vertices, edges, version, payload);
+ }
+
private GraphEvent publishEvent(GraphEvent event) throws CrudException {
GraphEventEnvelope response = sendAndWait(event);
responseHandler.handleBulkEventResponse(event, response);
diff --git a/src/main/java/org/onap/crud/service/CrudGraphDataService.java b/src/main/java/org/onap/crud/service/CrudGraphDataService.java
index 034b0bf..3916bc6 100644
--- a/src/main/java/org/onap/crud/service/CrudGraphDataService.java
+++ b/src/main/java/org/onap/crud/service/CrudGraphDataService.java
@@ -23,21 +23,32 @@ package org.onap.crud.service;
import java.util.HashMap;
import java.util.List;
+
import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.HttpHeaders;
+
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.onap.aai.cl.api.Logger;
+import org.onap.aai.cl.eelf.LoggerFactory;
import org.onap.aai.restclient.client.OperationResult;
import org.onap.crud.dao.GraphDao;
+import org.onap.crud.dao.champ.ChampBulkPayload;
+import org.onap.crud.dao.champ.ChampBulkPayloadResponse;
import org.onap.crud.entity.Edge;
import org.onap.crud.entity.Vertex;
import org.onap.crud.exception.CrudException;
+import org.onap.crud.logging.CrudServiceMsgs;
+import org.onap.crud.service.BulkPayload;
import org.onap.crud.parser.CrudResponseBuilder;
import org.onap.crud.util.CrudServiceUtil;
import org.onap.schema.OxmModelValidator;
import org.onap.schema.RelationshipSchemaValidator;
+import com.google.gson.GsonBuilder;
-public class CrudGraphDataService extends AbstractGraphDataService {
+public class CrudGraphDataService extends AbstractGraphDataService {
+ Logger logger = LoggerFactory.getInstance().getLogger(CrudGraphDataService.class.getName());
public CrudGraphDataService(GraphDao dao) throws CrudException {
super();
@@ -168,34 +179,16 @@ public class CrudGraphDataService extends AbstractGraphDataService {
Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(Edge.fromJson(operationResult.getResult()), version, payload);
return updateEdge(version, patchedEdge);
}
-
- @Override
- protected Vertex addBulkVertex(Vertex vertex, String version, String dbTransId) throws CrudException {
- return dao.addVertex(vertex.getType(), vertex.getProperties(), version, dbTransId);
- }
-
- @Override
- protected Vertex updateBulkVertex(Vertex vertex, String id, String version, String dbTransId) throws CrudException {
- return dao.updateVertex(id, vertex.getType(), vertex.getProperties(), version, dbTransId);
- }
-
- @Override
- protected void deleteBulkVertex(String id, String version, String type, String dbTransId) throws CrudException {
- dao.deleteVertex(id, type, dbTransId);
- }
-
- @Override
- protected Edge addBulkEdge(Edge edge, String version, String dbTransId) throws CrudException {
- return dao.addEdge(edge.getType(), edge.getSource(), edge.getTarget(), edge.getProperties(), version, dbTransId);
- }
-
- @Override
- protected Edge updateBulkEdge(Edge edge, String version, String dbTransId) throws CrudException {
- return dao.updateEdge(edge, dbTransId);
- }
-
+
@Override
- protected void deleteBulkEdge(String id, String version, String dbTransId) throws CrudException {
- dao.deleteEdge(id, dbTransId);
+ public String addBulk(String version, BulkPayload payload, HttpHeaders headers) throws CrudException {
+ ChampBulkPayload champPayload = new ChampBulkPayload();
+ champPayload.fromGizmoPayload(payload, version, headers, dao);
+ logger.info(CrudServiceMsgs.CHAMP_BULK_OP_INFO, "ChampBulkPayload-> "+new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create().toJson(champPayload));
+ OperationResult bulkResult = dao.bulkOperation(champPayload);
+
+ ChampBulkPayloadResponse response = ChampBulkPayloadResponse.fromJson(bulkResult.getResult());
+ response.populateChampData(version);
+ return CrudResponseBuilder.buildUpsertBulkResponse(response.getVertices(), response.getEdges(), version, payload);
}
}