summaryrefslogtreecommitdiffstats
path: root/aai-resources/src/main/java/org
diff options
context:
space:
mode:
authorVenkata Harish K Kajur <vk250x@att.com>2017-05-12 17:28:40 -0400
committerVenkata Harish K Kajur <vk250x@att.com>2017-05-12 17:30:49 -0400
commitc0e8c47e202ef604b449e72556c8757764744f7d (patch)
tree9c67ffb0bf962850999e42cae909a31b2b725c7d /aai-resources/src/main/java/org
parent2801d04f58b28ed4bc94cd1263bad7b6784c895e (diff)
Add all of the resources repo
Change-Id: If2a9c584621f6d01eb70e9c51e05e054ef3486c4 Signed-off-by: Venkata Harish K Kajur <vk250x@att.com>
Diffstat (limited to 'aai-resources/src/main/java/org')
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsErrorMessageLookupService.java98
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java54
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesListener.java37
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java126
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertyService.java218
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java37
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java95
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java198
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java44
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/interceptors/AAIHeaderProperties.java26
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java283
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java323
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/interceptors/PostAaiAjscInterceptor.java63
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/interceptors/PreAaiAjscInterceptor.java54
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java42
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/BulkConsumer.java484
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/BulkProcessConsumer.java42
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java104
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java129
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java583
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java120
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java145
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/db/DBRequest.java251
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java570
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/retired/RetiredConsumer.java143
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/retired/V3ThroughV7Consumer.java28
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java96
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java178
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java121
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/util/LogFormatTools.java36
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java160
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/transforms/Converter.java25
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/transforms/LowerCamelToLowerHyphenConverter.java34
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverter.java81
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/transforms/MapTraverser.java87
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java104
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java142
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/util/MergeResource.java205
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/util/PojoUtils.java738
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java283
-rw-r--r--aai-resources/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java264
41 files changed, 6851 insertions, 0 deletions
diff --git a/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsErrorMessageLookupService.java b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsErrorMessageLookupService.java
new file mode 100644
index 0000000..30dfced
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsErrorMessageLookupService.java
@@ -0,0 +1,98 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.ajsc_aai;
+
+//import java.util.HashMap;
+//import java.util.Map;
+
+//import javax.ws.rs.GET;
+//import javax.ws.rs.HeaderParam;
+//import javax.ws.rs.Path;
+//import javax.ws.rs.PathParam;
+//import javax.ws.rs.Produces;
+
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.web.context.ContextLoader;
+//import org.springframework.web.context.WebApplicationContext;
+
+//import ajsc.ErrorMessageLookupService;
+
+//@Path("/errormessage")
+//public class JaxrsErrorMessageLookupService {
+
+ //private final static Logger logger = LoggerFactory
+ //.getLogger(ErrorMessageLookupService.class);
+
+ /**
+ * Gets the message.
+ *
+ * @param input the input
+ * @param errorCode the error code
+ * @param appId the app id
+ * @param operation the operation
+ * @param messageText the message text
+ * @param isRESTService the is REST service
+ * @param faultEntity the fault entity
+ * @param ConvID the conv ID
+ * @return the message
+ */
+ //@GET
+ //@Path("/emls")
+ //@Produces("text/plain")
+ //public String getMessage(@PathParam("input") String input,
+ //@HeaderParam("errorCode") String errorCode,
+ //@HeaderParam("appId") String appId,
+ //@HeaderParam("operation") String operation,
+ //@HeaderParam("messageText") String messageText,
+ //@HeaderParam("isRESTService") String isRESTService,
+ //@HeaderParam("faultEntity") String faultEntity,
+ //@HeaderParam("ConvID") String ConvID) {
+
+ //Map<String, String> headers = new HashMap<String, String>();
+ //headers.put(errorCode, errorCode);
+ //headers.put(appId, appId);
+ //headers.put(operation, operation);
+ //headers.put(messageText, messageText);
+ //headers.put(isRESTService, isRESTService);
+ //headers.put(faultEntity, faultEntity);
+ //headers.put(ConvID, ConvID);
+
+ //WebApplicationContext applicationContext = ContextLoader
+ //.getCurrentWebApplicationContext();
+
+ //ErrorMessageLookupService e = (ErrorMessageLookupService) applicationContext
+ //.getBean("errorMessageLookupService");
+
+ //String message = e.getExceptionDetails(appId, operation, errorCode,
+ //messageText,isRESTService, faultEntity, ConvID);
+
+ //System.out.println("Error code = " + errorCode);
+ //System.out.println("appId = " + appId);
+ //System.out.println("operation = " + operation);
+ //System.out.println("messageText = " + messageText);
+ //System.out.println("isRESTService = " + isRESTService);
+ //System.out.println("faultEntity = " + faultEntity);
+ //System.out.println("ConvID = " + ConvID);
+ //return "The exception message is:\n " + message;
+ //}
+
+//}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java
new file mode 100644
index 0000000..39c78f6
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/JaxrsUserService.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.ajsc_aai;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import java.util.Map;
+import java.util.HashMap;
+
+@Path("/user")
+public class JaxrsUserService {
+
+ private static final Map<String,String> userIdToNameMap;
+ static {
+ userIdToNameMap = new HashMap<String,String>();
+ userIdToNameMap.put("userID1","Name1");
+ userIdToNameMap.put("userID2","Name2");
+ }
+
+ /**
+ * Lookup user.
+ *
+ * @param userId the user id
+ * @return the string
+ */
+ @GET
+ @Path("/{userId}")
+ @Produces("text/plain")
+ public String lookupUser(@PathParam("userId") String userId) {
+ String name = userIdToNameMap.get(userId);
+ return name != null ? name : "unknown id";
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesListener.java b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesListener.java
new file mode 100644
index 0000000..1520722
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesListener.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.ajsc_aai.filemonitor;
+
+import java.io.File;
+
+//import com.att.ssf.filemonitor.FileChangedListener;
+
+//public class ServicePropertiesListener implements FileChangedListener {
+
+ /**
+ * {@inheritDoc}
+ */
+ //@Override
+ //public void update(File file) throws Exception
+ //{
+ //ServicePropertiesMap.refresh(file);
+ //}
+//}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java
new file mode 100644
index 0000000..656b290
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertiesMap.java
@@ -0,0 +1,126 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.ajsc_aai.filemonitor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class ServicePropertiesMap
+{
+ private static HashMap<String, HashMap<String, String>> mapOfMaps = new HashMap<String, HashMap<String, String>>();
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ServicePropertiesMap.class);
+
+ /**
+ * Refresh.
+ *
+ * @param file the file
+ * @throws Exception the exception
+ */
+ public static void refresh(File file) throws Exception
+ {
+ try
+ {
+ LOGGER.info("Loading properties - " + (file != null?file.getName():""));
+
+ //Store .json & .properties files into map of maps
+ String filePath = file.getPath();
+
+ if(filePath.lastIndexOf(".json")>0){
+
+ ObjectMapper om = new ObjectMapper();
+ TypeReference<HashMap<String, String>> typeRef = new TypeReference<HashMap<String, String>>() {};
+ HashMap<String, String> propMap = om.readValue(file, typeRef);
+ HashMap<String, String> lcasePropMap = new HashMap<String, String>();
+ for (String key : propMap.keySet() )
+ {
+ String lcaseKey = ifNullThenEmpty(key);
+ lcasePropMap.put(lcaseKey, propMap.get(key));
+ }
+
+ mapOfMaps.put(file.getName(), lcasePropMap);
+
+
+ }else if(filePath.lastIndexOf(".properties")>0){
+ Properties prop = new Properties();
+ FileInputStream fis = new FileInputStream(file);
+ prop.load(fis);
+
+ @SuppressWarnings("unchecked")
+ HashMap<String, String> propMap = new HashMap<String, String>((Map)prop);
+
+ mapOfMaps.put(file.getName(), propMap);
+ }
+
+ LOGGER.info("File - " + file.getName() + " is loaded into the map and the corresponding system properties have been refreshed");
+ }
+ catch (Exception e)
+ {
+ LOGGER.error("File " + (file != null?file.getName():"") + " cannot be loaded into the map ", e);
+ throw new Exception("Error reading map file " + (file != null?file.getName():""), e);
+ }
+ }
+
+ /**
+ * Gets the property.
+ *
+ * @param fileName the file name
+ * @param propertyKey the property key
+ * @return the property
+ */
+ public static String getProperty(String fileName, String propertyKey)
+ {
+ HashMap<String, String> propMap = mapOfMaps.get(fileName);
+ return propMap!=null?propMap.get(ifNullThenEmpty(propertyKey)):"";
+ }
+
+ /**
+ * Gets the properties.
+ *
+ * @param fileName the file name
+ * @return the properties
+ */
+ public static HashMap<String, String> getProperties(String fileName){
+ return mapOfMaps.get(fileName);
+ }
+
+ /**
+ * If null then empty.
+ *
+ * @param key the key
+ * @return the string
+ */
+ private static String ifNullThenEmpty(String key) {
+ if (key == null) {
+ return "";
+ } else {
+ return key;
+ }
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertyService.java b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertyService.java
new file mode 100644
index 0000000..98426ad
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/filemonitor/ServicePropertyService.java
@@ -0,0 +1,218 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.ajsc_aai.filemonitor;
+
+//import java.io.File;
+//import java.io.FileInputStream;
+//import java.io.IOException;
+//import java.lang.reflect.Method;
+//import java.util.ArrayList;
+//import java.util.List;
+//import java.util.Properties;
+
+//import javax.annotation.PostConstruct;
+
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+
+//import com.att.ssf.filemonitor.FileChangedListener;
+//import com.att.ssf.filemonitor.FileMonitor;
+
+//public class ServicePropertyService {
+ //private boolean loadOnStartup;
+ //private ServicePropertiesListener fileChangedListener;
+ //private ServicePropertiesMap filePropertiesMap;
+ //private String ssfFileMonitorPollingInterval;
+ //private String ssfFileMonitorThreadpoolSize;
+ //private List<File> fileList;
+ //private static final String FILE_CHANGE_LISTENER_LOC = System
+ //.getProperty("AJSC_CONF_HOME") + "/etc";
+ //private static final String USER_CONFIG_FILE = "service-file-monitor.properties";
+ //static final Logger logger = LoggerFactory
+ //.getLogger(ServicePropertyService.class);
+
+ //// do not remove the postConstruct annotation, init method will not be
+ //// called after constructor
+ /**
+ * Inits the.
+ *
+ * @throws Exception the exception
+ */
+ //@PostConstruct
+ //public void init() throws Exception {
+
+ //try {
+ //getFileList(FILE_CHANGE_LISTENER_LOC);
+
+ //for (File file : fileList) {
+ //try {
+ //FileChangedListener fileChangedListener = this.fileChangedListener;
+ //Object filePropertiesMap = this.filePropertiesMap;
+ //Method m = filePropertiesMap.getClass().getMethod(
+ //"refresh", File.class);
+ //m.invoke(filePropertiesMap, file);
+ //FileMonitor fm = FileMonitor.getInstance();
+ //fm.addFileChangedListener(file, fileChangedListener,
+ //loadOnStartup);
+ //} catch (Exception ioe) {
+ //logger.error("Error in the file monitor block", ioe);
+ //}
+ //}
+ //} catch (Exception ex) {
+ //logger.error("Error creating property map ", ex);
+ //}
+
+ //}
+
+ /**
+ * Gets the file list.
+ *
+ * @param dirName the dir name
+ * @return the file list
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ //private void getFileList(String dirName) throws IOException {
+ //File directory = new File(dirName);
+ //FileInputStream fis = null;
+
+ //if (fileList == null)
+ //fileList = new ArrayList<File>();
+
+ //// get all the files that are ".json" or ".properties", from a directory
+ //// & it's sub-directories
+ //File[] fList = directory.listFiles();
+
+ //for (File file : fList) {
+ //// read service property files from the configuration file
+ //if (file.isFile() && file.getPath().endsWith(USER_CONFIG_FILE)) {
+ //try {
+ //fis = new FileInputStream(file);
+ //Properties prop = new Properties();
+ //prop.load(fis);
+
+ //for (String filePath : prop.stringPropertyNames()) {
+ //fileList.add(new File(prop.getProperty(filePath)));
+ //}
+ //} catch (Exception ioe) {
+ //logger.error("Error reading the file stream ", ioe);
+ //} finally {
+ //fis.close();
+ //}
+ //} else if (file.isDirectory()) {
+ //getFileList(file.getPath());
+ //}
+ //}
+
+ //}
+
+ /**
+ * Sets the load on startup.
+ *
+ * @param loadOnStartup the new load on startup
+ */
+ //public void setLoadOnStartup(boolean loadOnStartup) {
+ //this.loadOnStartup = loadOnStartup;
+ //}
+
+ /**
+ * Sets the ssf file monitor polling interval.
+ *
+ * @param ssfFileMonitorPollingInterval the new ssf file monitor polling interval
+ */
+ //public void setSsfFileMonitorPollingInterval(
+ //String ssfFileMonitorPollingInterval) {
+ //this.ssfFileMonitorPollingInterval = ssfFileMonitorPollingInterval;
+ //}
+
+ /**
+ * Sets the ssf file monitor threadpool size.
+ *
+ * @param ssfFileMonitorThreadpoolSize the new ssf file monitor threadpool size
+ */
+ //public void setSsfFileMonitorThreadpoolSize(
+ //String ssfFileMonitorThreadpoolSize) {
+ //this.ssfFileMonitorThreadpoolSize = ssfFileMonitorThreadpoolSize;
+ //}
+
+ /**
+ * Gets the load on startup.
+ *
+ * @return the load on startup
+ */
+ //public boolean getLoadOnStartup() {
+ //return loadOnStartup;
+ //}
+
+ /**
+ * Gets the ssf file monitor polling interval.
+ *
+ * @return the ssf file monitor polling interval
+ */
+ //public String getSsfFileMonitorPollingInterval() {
+ //return ssfFileMonitorPollingInterval;
+ //}
+
+ /**
+ * Gets the ssf file monitor threadpool size.
+ *
+ * @return the ssf file monitor threadpool size
+ */
+ //public String getSsfFileMonitorThreadpoolSize() {
+ //return ssfFileMonitorThreadpoolSize;
+ //}
+
+ /**
+ * Gets the file changed listener.
+ *
+ * @return the file changed listener
+ */
+ //public ServicePropertiesListener getFileChangedListener() {
+ //return fileChangedListener;
+ //}
+
+ /**
+ * Sets the file changed listener.
+ *
+ * @param fileChangedListener the new file changed listener
+ */
+ //public void setFileChangedListener(
+ //ServicePropertiesListener fileChangedListener) {
+ //this.fileChangedListener = fileChangedListener;
+ //}
+
+ /**
+ * Gets the file properties map.
+ *
+ * @return the file properties map
+ */
+ //public ServicePropertiesMap getFilePropertiesMap() {
+ //return filePropertiesMap;
+ //}
+
+ /**
+ * Sets the file properties map.
+ *
+ * @param filePropertiesMap the new file properties map
+ */
+ //public void setFilePropertiesMap(ServicePropertiesMap filePropertiesMap) {
+ //this.filePropertiesMap = filePropertiesMap;
+ //}
+//}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java
new file mode 100644
index 0000000..7577de7
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/ajsc_aai/util/ServicePropertiesMapBean.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.ajsc_aai.util;
+
+import org.openecomp.aai.ajsc_aai.filemonitor.ServicePropertiesMap;
+
+public class ServicePropertiesMapBean {
+
+ /**
+ * Gets the property.
+ *
+ * @param propFileName the prop file name
+ * @param propertyKey the property key
+ * @return the property
+ */
+ public static String getProperty(String propFileName, String propertyKey) {
+ return ServicePropertiesMap.getProperty(propFileName, propertyKey);
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java b/aai-resources/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java
new file mode 100644
index 0000000..458c4c9
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/db/schema/ScriptDriver.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.db.schema;
+
+import java.io.IOException;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.util.AAIConfig;
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+public class ScriptDriver {
+
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws AAIException the AAI exception
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public static void main (String[] args) throws AAIException, JsonGenerationException, JsonMappingException, IOException {
+ CommandLineArgs cArgs = new CommandLineArgs();
+
+ new JCommander(cArgs, args);
+
+ if (cArgs.help) {
+ System.out.println("-c [path to graph configuration] -type [what you want to audit - oxm or graph]");
+ }
+ String config = cArgs.config;
+ AAIConfig.init();
+ TitanGraph graph = TitanFactory.open(config);
+ if (!(cArgs.type.equals("oxm") || cArgs.type.equals("graph"))) {
+ System.out.println("type: " + cArgs.type + " not recognized.");
+ System.exit(1);
+ }
+
+ Auditor a = null;
+ if (cArgs.type.equals("oxm")) {
+ a = AuditorFactory.getOXMAuditor(Version.v8);
+ } else if (cArgs.type.equals("graph")) {
+ a = AuditorFactory.getGraphAuditor(graph);
+ }
+
+ AuditDoc doc = a.getAuditDoc();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(doc);
+ System.out.println(json);
+
+ }
+
+}
+
+class CommandLineArgs {
+
+ @Parameter(names = "--help", description = "Help")
+ public boolean help = false;
+
+ @Parameter(names = "-c", description = "Configuration", required=true)
+ public String config;
+
+ @Parameter(names = "-type", description = "Type", required=true)
+ public String type = "graph";
+
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java
new file mode 100644
index 0000000..fc11e5d
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java
@@ -0,0 +1,198 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.dmaap;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.TextMessage;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.log4j.MDC;
+import org.eclipse.jetty.util.security.Password;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.util.AAIConstants;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+//import com.att.nsa.mr.client.MRBatchingPublisher;
+//import com.att.nsa.mr.client.MRClientFactory;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
+
+public class AAIDmaapEventJMSConsumer implements MessageListener {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIDmaapEventJMSConsumer.class);
+
+ private Client httpClient;
+
+ //private MRBatchingPublisher aaiEventPublisher = null;
+ private Properties aaiEventProps;
+ private String aaiEventUrl = "";
+
+ //private MRBatchingPublisher aaiVceEventPublisher = null;
+ private Properties aaiVceEventProps;
+ private String aaiVceEventUrl = "";
+
+ public AAIDmaapEventJMSConsumer() throws org.apache.commons.configuration.ConfigurationException {
+ //super();
+ //try {
+
+ //if (this.aaiEventPublisher == null) {
+ //FileReader reader = new FileReader(new File(AAIConstants.AAI_EVENT_DMAAP_PROPS));
+ //aaiEventProps = new Properties();
+ //aaiEventProps.load(reader);
+ //reader.close();
+ //aaiEventProps.setProperty("DME2preferredRouterFilePath",
+ //AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "preferredRoute.txt");
+ //if (aaiEventProps.getProperty("password") != null
+ //&& aaiEventProps.getProperty("password").startsWith("OBF:")) {
+ //aaiEventProps.setProperty("password", Password.deobfuscate(aaiEventProps.getProperty("password")));
+ //}
+
+ //this.aaiEventPublisher = MRClientFactory.createBatchingPublisher(aaiEventProps);
+
+ //String host = aaiEventProps.getProperty("host");
+ //String topic = aaiEventProps.getProperty("topic");
+ //String protocol = aaiEventProps.getProperty("Protocol");
+
+ //String username = aaiEventProps.getProperty("username");
+ //String password = aaiEventProps.getProperty("password");
+
+ //aaiEventUrl = protocol + "://" + host + "/events/" + topic;
+ //httpClient = Client.create();
+ //httpClient.addFilter(new HTTPBasicAuthFilter(username, password));
+ //}
+
+ //if (this.aaiVceEventProps == null) {
+ //FileReader reader = new FileReader(new File(AAIConstants.AAI_EVENT_DMAAP_PROPS));
+ //aaiVceEventProps = new Properties();
+ //aaiVceEventProps.load(reader);
+ //reader.close();
+ //aaiVceEventProps.setProperty("DME2preferredRouterFilePath",
+ //AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "preferredRoute.txt");
+ //if (aaiVceEventProps.getProperty("password") != null
+ //&& aaiVceEventProps.getProperty("password").startsWith("OBF:")) {
+ //aaiVceEventProps.setProperty("password",
+ //Password.deobfuscate(aaiVceEventProps.getProperty("password")));
+ //}
+ //aaiVceEventProps.setProperty("topic", "AAI-VCE-INTERFACE-DATA");
+ //this.aaiVceEventPublisher = MRClientFactory.createBatchingPublisher(aaiVceEventProps);
+
+ //String host = aaiVceEventProps.getProperty("host");
+ //String topic = aaiVceEventProps.getProperty("topic");
+ //String protocol = aaiVceEventProps.getProperty("Protocol");
+
+ //aaiVceEventUrl = protocol + "://" + host + "/events/" + topic;
+
+ //}
+ //} catch (IOException e) {
+ //ErrorLogHelper.logError("AAI_4000", "Error updating dmaap config file for aai event.");
+ //}
+
+ }
+
+ @Override
+ public void onMessage(Message message) {
+
+ //String jsmMessageTxt = "";
+ //String aaiEvent = "";
+ //String eventName = "";
+
+
+ //String environment = "";
+
+ //if (message instanceof TextMessage) {
+ //try {
+ //jsmMessageTxt = ((TextMessage) message).getText();
+ //JSONObject jo = new JSONObject(jsmMessageTxt);
+
+ //if (jo.has("aaiEventPayload")) {
+ //aaiEvent = jo.getJSONObject("aaiEventPayload").toString();
+ //} else {
+ //return;
+ //}
+ //if (jo.getString("transId") != null) {
+ //MDC.put("requestId", jo.getString("transId"));
+ //}
+ //if (jo.getString("fromAppId") != null) {
+ //MDC.put("partnerName", jo.getString("fromAppId"));
+ //}
+ //if (jo.getString("event-topic") != null) {
+ //eventName = jo.getString("event-topic");
+ //}
+
+ //LOGGER.info(eventName + "|" + aaiEvent);
+ //if (eventName.equals("AAI-EVENT")) {
+ //if (!this.sentWithHttp(environment, this.httpClient, this.aaiEventUrl, aaiEvent)) {
+ //this.aaiEventPublisher.send(aaiEvent);
+ //}
+ //LOGGER.info(eventName + "|Event sent.");
+ //} else if (eventName.equals("AAI-VCE-INTERFACE-DATA")) {
+ //String msg = "";
+ //if (!this.sentWithHttp(environment, this.httpClient, this.aaiVceEventUrl, aaiEvent)) {
+ //this.aaiVceEventPublisher.send(aaiEvent);
+ //msg = this.aaiVceEventPublisher.sendBatchWithResponse().getResponseMessage();
+ //}
+ //LOGGER.info(eventName + "|Event sent. " + msg);
+ //} else {
+ //LOGGER.error(eventName + "|Event Topic invalid.");
+ //}
+ //} catch (java.net.SocketException e) {
+ //if (!e.getMessage().contains("Connection reset")) {
+ //LOGGER.error("AAI_7304 Error reaching DMaaP to send event. " + aaiEvent, e);
+ //}
+ //} catch (IOException e) {
+ //LOGGER.error("AAI_7304 Error reaching DMaaP to send event. " + aaiEvent, e);
+ //} catch (JMSException | JSONException e) {
+ //LOGGER.error("AAI_7350 Error parsing aaievent jsm message for sending to dmaap. " + jsmMessageTxt, e);
+ //} catch (Exception e) {
+ //LOGGER.error("AAI_7350 Error sending message to dmaap. " + jsmMessageTxt, e);
+ //}
+ //}
+
+ }
+
+ private boolean sentWithHttp(String environment, Client client, String url, String aaiEvent) throws IOException {
+ //if (environment.startsWith("dev") || environment.startsWith("testINT") || environment.startsWith("testEXT")) {
+
+ //WebResource webResource = client.resource(url);
+ //ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON)
+ //.post(ClientResponse.class, aaiEvent);
+ //if (response.getStatus() != 200) {
+ //LOGGER.info("Failed : HTTP error code : " + response.getStatus());
+ //return false;
+ //}
+ //} else {
+ //return false;
+ //}
+ return true;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java b/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java
new file mode 100644
index 0000000..eef852a
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSProducer.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.dmaap;
+
+import org.apache.activemq.ActiveMQConnectionFactory;
+import org.apache.activemq.command.ActiveMQQueue;
+import org.json.JSONObject;
+import org.springframework.jms.connection.CachingConnectionFactory;
+import org.springframework.jms.core.JmsTemplate;
+
+public class AAIDmaapEventJMSProducer {
+
+ private JmsTemplate jmsTemplate;
+
+ public AAIDmaapEventJMSProducer() {
+ //this.jmsTemplate = new JmsTemplate();
+ //this.jmsTemplate.setConnectionFactory(new CachingConnectionFactory(new ActiveMQConnectionFactory("tcp://localhost:61447")));
+ //this.jmsTemplate.setDefaultDestination(new ActiveMQQueue("IN_QUEUE"));
+ }
+
+ public void sendMessageToDefaultDestination(JSONObject finalJson) {
+ //jmsTemplate.convertAndSend(finalJson.toString());
+ //CachingConnectionFactory ccf = (CachingConnectionFactory)this.jmsTemplate.getConnectionFactory();
+ //ccf.destroy();
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAIHeaderProperties.java b/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAIHeaderProperties.java
new file mode 100644
index 0000000..4798d90
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAIHeaderProperties.java
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.interceptors;
+
+public class AAIHeaderProperties {
+
+ public static final String REQUEST_CONTEXT = "aai-request-context";
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java b/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java
new file mode 100644
index 0000000..80127d0
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSInInterceptor.java
@@ -0,0 +1,283 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.interceptors;
+
+import java.io.InputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.ws.rs.core.MediaType;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.interceptor.LoggingMessage;
+import org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor;
+import org.apache.cxf.message.Message;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.rest.util.EchoResponse;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import org.openecomp.aai.util.HbaseSaltPrefixer;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+public class AAILogJAXRSInInterceptor extends JAXRSInInterceptor {
+
+ protected final String COMPONENT = "aairest";
+ protected final String CAMEL_REQUEST ="CamelHttpUrl";
+ private static final Pattern uuidPattern = Pattern.compile("^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$");
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAILogJAXRSInInterceptor.class);
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handleMessage(Message message) {
+
+ boolean go = false;
+ String uri = null;
+ String query = null;
+ try {
+
+ uri = (String)message.get(CAMEL_REQUEST);
+ if (uri != null) {
+ query = (String)message.get(Message.QUERY_STRING);
+ }
+
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_INTERCEPTOR).equalsIgnoreCase("true") &&
+ AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_ENABLED).equalsIgnoreCase("true")) {
+ go = true;
+ message.getExchange().put("AAI_LOGGING_HBASE_ENABLED", 1);
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGREQUEST).equalsIgnoreCase("true") ) {
+ message.getExchange().put("AAI_LOGGING_HBASE_LOGREQUEST", 1);
+ }
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_HBASE_LOGRESPONSE).equalsIgnoreCase("true") ) {
+ message.getExchange().put("AAI_LOGGING_HBASE_LOGRESPONSE", 1);
+ }
+ }
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_ENABLED).equalsIgnoreCase("true") ) {
+ go = true;
+ message.getExchange().put("AAI_LOGGING_TRACE_ENABLED", 1);
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGREQUEST).equalsIgnoreCase("true") ) {
+ message.getExchange().put("AAI_LOGGING_TRACE_LOGREQUEST", 1);
+ }
+ if (AAIConfig.get(AAIConstants.AAI_LOGGING_TRACE_LOGRESPONSE).equalsIgnoreCase("true") ) {
+ message.getExchange().put("AAI_LOGGING_TRACE_LOGRESPONSE", 1);
+ }
+ }
+ } catch (AAIException e1) {
+ ErrorLogHelper.logException(e1);
+ }
+
+ if (uri.contains(EchoResponse.echoPath)) {
+ // if it's a health check, we don't want to log ANYTHING if it's a lightweight one
+ if (query == null) {
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")) {
+ message.getExchange().remove("AAI_LOGGING_HBASE_ENABLED");
+ }
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
+ message.getExchange().remove("AAI_LOGGING_TRACE_ENABLED");
+ }
+ go = false;
+ }
+ }
+ else if (uri.contains("/translog/")) {
+ // if it's a translog query, we don't want to log the responses
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGRESPONSE")) {
+ message.getExchange().remove("AAI_LOGGING_HBASE_LOGRESPONSE");
+ }
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGRESPONSE")) {
+ message.getExchange().remove("AAI_LOGGING_TRACE_LOGRESPONSE");
+ }
+ }
+
+ if (go == false) { // there's nothing to do
+ return;
+ }
+
+ // DONE: get a TXID based on hostname, time (YYYYMMDDHHMMSSMILLIS, and LoggingMessage.nextId(); 20150326145301-1
+ String now = genDate();
+
+ message.getExchange().put("AAI_RQST_TM", now);
+
+ String id = (String)message.getExchange().get(LoggingMessage.ID_KEY);
+
+ String fullId = null;
+ try {
+ if (id == null) {
+ id = LoggingMessage.nextId();
+ }
+ fullId = AAIConfig.get(AAIConstants.AAI_NODENAME) + "-" + now + "-" + id;
+ fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
+ message.getExchange().put(LoggingMessage.ID_KEY, fullId);
+ } catch (AAIException e1) {
+ LOGGER.debug("config problem", e1);
+ }
+
+ if (fullId == null) {
+ fullId = now + "-" + id;
+ fullId = HbaseSaltPrefixer.getInstance().prependSalt(fullId);
+ }
+ message.put(LoggingMessage.ID_KEY, fullId);
+ final LoggingMessage buffer = new LoggingMessage("Message", fullId);
+
+ Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE);
+ if (responseCode != null) {
+ buffer.getResponseCode().append(responseCode);
+ }
+
+ String encoding = (String)message.get(Message.ENCODING);
+
+ if (encoding != null) {
+ buffer.getEncoding().append(encoding);
+ }
+ String httpMethod = (String)message.get(Message.HTTP_REQUEST_METHOD);
+ if (httpMethod != null) {
+ buffer.getHttpMethod().append(httpMethod);
+ }
+
+ String ct = (String)message.get(Message.CONTENT_TYPE);
+ if (ct != null) {
+ if ("*/*".equals(ct)) {
+ message.put(Message.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ ct = MediaType.APPLICATION_JSON;
+ }
+ buffer.getContentType().append(ct);
+
+ }
+ Object headers = message.get(Message.PROTOCOL_HEADERS);
+ if (headers != null) {
+ buffer.getHeader().append(headers);
+
+ Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
+ String transId = "";
+ List<String> xt = headersList.get("X-TransactionId");
+ String newTransId = transId;
+ boolean missingTransId = false;
+ boolean replacedTransId = false;
+ String logMsg = null;
+ if (xt != null) {
+ for (String transIdValue : xt) {
+ transId = transIdValue;
+ }
+ Matcher matcher = uuidPattern.matcher(transId);
+ if (!matcher.find()) {
+ replacedTransId = true;
+ // check if there's a colon, and check the first group?
+ if (transId.contains(":")) {
+ String[] uuidParts = transId.split(":");
+ Matcher matcher2 = uuidPattern.matcher(uuidParts[0]);
+ if (matcher2.find()) {
+ newTransId = uuidParts[0];
+ } else {
+ // punt, we tried to find it, it has a colon but no UUID-1
+ newTransId = UUID.randomUUID().toString();
+ }
+ } else {
+ newTransId = UUID.randomUUID().toString();
+ }
+ }
+ } else {
+ newTransId = UUID.randomUUID().toString();
+ missingTransId = true;
+ }
+
+ if (missingTransId || replacedTransId) {
+ List<String> txList = new ArrayList<String>();
+ txList.add(newTransId);
+ headersList.put("X-TransactionId", txList);
+ if (missingTransId) {
+ logMsg = "Missing requestID. Assigned " + newTransId;
+ } else if (replacedTransId) {
+ logMsg = "Replaced invalid requestID of " + transId + " Assigned " + newTransId;
+ }
+ }
+
+ List<String> contentType = headersList.get("Content-Type");
+ if (contentType == null) {
+ ct = (String)message.get(Message.CONTENT_TYPE);
+ headersList.put(Message.CONTENT_TYPE, Collections.singletonList(ct));
+ }
+
+ LOGGER.auditEvent("REST " + httpMethod + " " + ((query != null)? uri+"?"+query : uri) + " HbaseTxId=" + fullId);
+ LOGGER.info(logMsg);
+ }
+
+
+ if (uri != null) {
+ buffer.getAddress().append(uri);
+ if (query != null) {
+ buffer.getAddress().append("?").append(query);
+ }
+ }
+
+ InputStream is = message.getContent(InputStream.class);
+ if (is != null) {
+ try {
+ String currentPayload = IOUtils.toString(is, "UTF-8");
+ IOUtils.closeQuietly(is);
+ buffer.getPayload().append(currentPayload);
+ is = IOUtils.toInputStream(currentPayload, "UTF-8");
+ message.setContent(InputStream.class, is);
+ IOUtils.closeQuietly(is);
+ } catch (Exception e) {
+ // It's ok to not have request input content
+ // throw new Fault(e);
+ }
+ }
+
+ // this will be saved in the message exchange, and can be pulled out later...
+ message.getExchange().put(fullId + "_REQUEST", buffer.toString());
+ }
+
+ /**
+ * Gen date.
+ *
+ * @param aaiLogger the aai logger
+ * @param logline the logline
+ * @return the string
+ */
+ protected String genDate() {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (AAIException ex) {
+ ErrorLogHelper.logException(ex);
+ } finally {
+ if (formatter == null) {
+ formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
+ }
+ }
+
+ return formatter.format(date);
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java b/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java
new file mode 100644
index 0000000..0f5e457
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/interceptors/AAILogJAXRSOutInterceptor.java
@@ -0,0 +1,323 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.interceptors;
+
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.interceptor.LoggingMessage;
+import org.apache.cxf.io.CacheAndWriteOutputStream;
+import org.apache.cxf.io.CachedOutputStream;
+import org.apache.cxf.io.CachedOutputStreamCallback;
+import org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor;
+import org.apache.cxf.message.Message;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.util.AAIConstants;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+// right after the request is complete, there may be content
+public class AAILogJAXRSOutInterceptor extends JAXRSOutInterceptor {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAILogJAXRSOutInterceptor.class);
+
+ protected final String COMPONENT = "aairest";
+ protected final String CAMEL_REQUEST = "CamelHttpUrl";
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handleMessage(Message message) {
+
+ String fullId = (String) message.getExchange().get(LoggingMessage.ID_KEY);
+
+ Map<String, List<String>> headers = CastUtils.cast((Map<?, ?>) message.get(Message.PROTOCOL_HEADERS));
+ if (headers == null) {
+ headers = new HashMap<String, List<String>>();
+ }
+
+ headers.put("X-AAI-TXID", Collections.singletonList(fullId));
+ message.put(Message.PROTOCOL_HEADERS, headers);
+
+ Message outMessage = message.getExchange().getOutMessage();
+ final OutputStream os = outMessage.getContent(OutputStream.class);
+ if (os == null) {
+ return;
+ }
+
+ // we only want to register the callback if there is good reason for it.
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED") || message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
+
+ final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(os);
+ message.setContent(OutputStream.class, newOut);
+ newOut.registerCallback(new LoggingCallback(message, os));
+ }
+
+ }
+
+ class LoggingCallback implements CachedOutputStreamCallback {
+
+ private final Message message;
+ private final OutputStream origStream;
+
+ public LoggingCallback(final Message msg, final OutputStream os) {
+ this.message = msg;
+ this.origStream = os;
+ }
+
+ public void onFlush(CachedOutputStream cos) {
+
+ }
+
+ public void onClose(CachedOutputStream cos) {
+
+ String getValue = "";
+ String postValue = "";
+ String logValue = "";
+
+ try {
+ logValue = AAIConfig.get("aai.transaction.logging");
+ getValue = AAIConfig.get("aai.transaction.logging.get");
+ postValue = AAIConfig.get("aai.transaction.logging.post");
+ } catch (AAIException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED") && !message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
+ return;
+ }
+
+ String fullId = (String) message.getExchange().get(LoggingMessage.ID_KEY);
+
+ Message inMessage = message.getExchange().getInMessage();
+ String transId = null;
+ String fromAppId = null;
+
+ Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>) inMessage.get(Message.PROTOCOL_HEADERS));
+ if (headersList != null) {
+ List<String> xt = headersList.get("X-TransactionId");
+ if (xt != null) {
+ for (String transIdValue : xt) {
+ transId = transIdValue;
+ }
+ }
+ List<String> fa = headersList.get("X-FromAppId");
+ if (fa != null) {
+ for (String fromAppIdValue : fa) {
+
+ fromAppId = fromAppIdValue;
+ }
+ }
+ }
+
+ String httpMethod = (String) inMessage.get(Message.HTTP_REQUEST_METHOD);
+
+ String uri = (String) inMessage.get(CAMEL_REQUEST);
+ String fullUri = uri;
+ if (uri != null) {
+ String query = (String) message.get(Message.QUERY_STRING);
+ if (query != null) {
+ fullUri = uri + "?" + query;
+ }
+ }
+
+ String request = (String) message.getExchange().get(fullId + "_REQUEST");
+
+ Message outMessage = message.getExchange().getOutMessage();
+
+ final LoggingMessage buffer = new LoggingMessage("OUTMessage", fullId);
+
+ // should we check this, and make sure it's not an error?
+ Integer responseCode = (Integer) outMessage.get(Message.RESPONSE_CODE);
+ if (responseCode == null) {
+ responseCode = 200; // this should never happen, but just in
+ // case we don't get one
+ }
+ buffer.getResponseCode().append(responseCode);
+
+ String encoding = (String) outMessage.get(Message.ENCODING);
+
+ if (encoding != null) {
+ buffer.getEncoding().append(encoding);
+ }
+
+ String ct = (String) outMessage.get(Message.CONTENT_TYPE);
+ if (ct != null) {
+ buffer.getContentType().append(ct);
+ }
+
+ Object headers = outMessage.get(Message.PROTOCOL_HEADERS);
+ if (headers != null) {
+ buffer.getHeader().append(headers);
+ }
+
+ Boolean ss = false;
+ if (responseCode >= 200 && responseCode <= 299) {
+ ss = true;
+ }
+ String response = buffer.toString();
+
+ // this should have been set by the in interceptor
+ String rqstTm = (String) message.getExchange().get("AAI_RQST_TM");
+
+ // just in case it wasn't, we'll put this here. not great, but it'll
+ // have a val.
+ if (rqstTm == null) {
+ rqstTm = genDate();
+ }
+
+
+ String respTm = genDate();
+
+ try {
+ String actualRequest = request;
+ StringBuilder builder = new StringBuilder();
+ cos.writeCacheTo(builder, 100000);
+ // here comes my xml:
+ String payload = builder.toString();
+
+ String actualResponse = response;
+ if (payload == null) {
+
+ } else {
+ actualResponse = response + payload;
+ }
+
+ // we only log to AAI log if it's eanbled in the config props
+ // file
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_ENABLED")) {
+
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGREQUEST")) {
+
+ // strip newlines from request
+ String traceRequest = actualRequest;
+ traceRequest = traceRequest.replace("\n", " ");
+ traceRequest = traceRequest.replace("\r", "");
+ traceRequest = traceRequest.replace("\t", "");
+ LOGGER.debug(traceRequest);
+ }
+ if (message.getExchange().containsKey("AAI_LOGGING_TRACE_LOGRESPONSE")) {
+ // strip newlines from response
+ String traceResponse = actualResponse;
+ traceResponse = traceResponse.replace("\n", " ");
+ traceResponse = traceResponse.replace("\r", "");
+ traceResponse = traceResponse.replace("\t", "");
+
+ LOGGER.debug(traceResponse);
+ }
+ }
+
+ // we only log to HBASE if it's enabled in the config props file
+ // TODO: pretty print XML/JSON. we might need to get the payload
+ // and envelope seperately
+ if (message.getExchange().containsKey("AAI_LOGGING_HBASE_ENABLED")) {
+ if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGREQUEST")) {
+ actualRequest = "loggingDisabled";
+ }
+ if (!message.getExchange().containsKey("AAI_LOGGING_HBASE_LOGRESPONSE")) {
+ actualResponse = "loggingDisabled";
+ }
+
+ LOGGER.debug("action={}, urlin={}, HbTransId={}", httpMethod, fullUri, fullId);
+
+ if (logValue.equals("false")) {
+ } else if (getValue.equals("false") && httpMethod.equals("GET")) {
+ } else if (postValue.equals("false") && httpMethod.equals("POST")) {
+ } else {
+ putTransaction(transId, responseCode.toString(), rqstTm, respTm, fromAppId + ":" + transId, fullUri, httpMethod, request, response, actualResponse);
+
+ }
+ }
+ } catch (Exception ex) {
+ // ignore
+ }
+
+ message.setContent(OutputStream.class, origStream);
+
+ LOGGER.auditEvent("HTTP Response Code: {}", responseCode.toString());
+ }
+
+ }
+
+ protected String genDate() {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (AAIException ex) {
+ ErrorLogHelper.logException(ex);
+ } finally {
+ if (formatter == null) {
+ formatter = new SimpleDateFormat("YYMMdd-HH:mm:ss:SSS");
+ }
+ }
+ return formatter.format(date);
+ }
+
+ public String putTransaction(String tid, String status, String rqstTm, String respTm, String srcId, String rsrcId, String rsrcType, String rqstBuf, String respBuf, String actualResponse) {
+ String tm = null;
+ String fromAppId = srcId.substring(0, srcId.indexOf(':'));
+ String transId = srcId.substring(srcId.indexOf(':') + 1);
+
+ if (tid == null || "".equals(tid)) {
+ Date date = new Date();
+ DateFormat formatter = null;
+ try {
+ formatter = new SimpleDateFormat(AAIConfig.get(AAIConstants.HBASE_TABLE_TIMESTAMP_FORMAT));
+ } catch (Exception e) {
+ formatter = new SimpleDateFormat("YYYYMMdd-HH:mm:ss:SSS");
+ }
+ tm = formatter.format(date);
+ tid = tm + "-";
+ }
+
+ String htid = tid;
+
+ if (rqstTm == null || "".equals(rqstTm)) {
+ rqstTm = tm;
+ }
+
+ if (respTm == null || "".equals(respTm)) {
+ respTm = tm;
+ }
+
+ try {
+ LOGGER.debug(" transactionId:" + tid + " status: " + status + " rqstDate: " + rqstTm + " respDate: " + respTm + " sourceId: " + srcId + " resourceId: "
+ + rsrcId + " resourceType: " + rsrcType + " payload rqstBuf: " + rqstBuf + " payload respBuf: " + respBuf + " Payload Error Messages: " + actualResponse);
+ return htid;
+ } catch (Exception e) {
+ ErrorLogHelper.logError("AAI_4000", "Exception updating HBase:");
+ return htid;
+ }
+
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/interceptors/PostAaiAjscInterceptor.java b/aai-resources/src/main/java/org/openecomp/aai/interceptors/PostAaiAjscInterceptor.java
new file mode 100644
index 0000000..3a4f899
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/interceptors/PostAaiAjscInterceptor.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.interceptors;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.aai.logging.LoggingContext;
+import org.openecomp.aai.logging.LoggingContext.StatusCode;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import ajsc.beans.interceptors.AjscInterceptor;
+
+public class PostAaiAjscInterceptor implements AjscInterceptor {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(PostAaiAjscInterceptor.class);
+
+ private static class LazyAaiAjscInterceptor {
+ public static final PostAaiAjscInterceptor INSTANCE = new PostAaiAjscInterceptor();
+ }
+
+ public static PostAaiAjscInterceptor getInstance() {
+ return LazyAaiAjscInterceptor.INSTANCE;
+ }
+
+ @Override
+ public boolean allowOrReject(HttpServletRequest req, HttpServletResponse resp, Map<?, ?> paramMap)
+ throws Exception {
+ final String responseCode = LoggingContext.responseCode();
+
+ if (responseCode != null && responseCode.startsWith("ERR.")) {
+ LoggingContext.statusCode(StatusCode.ERROR);
+ LOGGER.error(req.getRequestURL() + " call failed with responseCode=" + responseCode);
+ } else {
+ LoggingContext.statusCode(StatusCode.COMPLETE);
+ LOGGER.info(req.getRequestURL() + " call succeeded");
+ }
+
+ LoggingContext.clear();
+ return true;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/interceptors/PreAaiAjscInterceptor.java b/aai-resources/src/main/java/org/openecomp/aai/interceptors/PreAaiAjscInterceptor.java
new file mode 100644
index 0000000..a2c56d0
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/interceptors/PreAaiAjscInterceptor.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.interceptors;
+
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.openecomp.aai.logging.LoggingContext;
+
+import ajsc.beans.interceptors.AjscInterceptor;
+
+public class PreAaiAjscInterceptor implements AjscInterceptor {
+
+ private static class LazyAaiAjscInterceptor {
+ public static final PreAaiAjscInterceptor INSTANCE = new PreAaiAjscInterceptor();
+ }
+
+ public static PreAaiAjscInterceptor getInstance() {
+ return LazyAaiAjscInterceptor.INSTANCE;
+ }
+
+ @Override
+ public boolean allowOrReject(HttpServletRequest req, HttpServletResponse resp, Map<?, ?> paramMap)
+ throws Exception {
+
+ LoggingContext.init();
+
+ LoggingContext.requestId(req.getHeader("X-TransactionId"));
+ LoggingContext.partnerName(req.getHeader("X-FromAppId"));
+ LoggingContext.serviceName(req.getMethod() + " " + req.getRequestURI().toString());
+
+ return true;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java
new file mode 100644
index 0000000..f8c34c2
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/BulkAddConsumer.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest;
+
+import javax.ws.rs.Path;
+
+import org.openecomp.aai.restcore.HttpMethod;
+
+@Path("{version: v[8-9]|v1[0]}/bulkadd")
+public class BulkAddConsumer extends BulkConsumer {
+
+ @Override
+ protected boolean functionAllowed(HttpMethod method) {
+
+ return method.equals(HttpMethod.PUT);
+
+ }
+
+ @Override
+ protected boolean enableResourceVersion() {
+ return true;
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/BulkConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/BulkConsumer.java
new file mode 100644
index 0000000..951c9ff
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/BulkConsumer.java
@@ -0,0 +1,484 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.PUT;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.javatuples.Pair;
+import org.javatuples.Triplet;
+
+import org.openecomp.aai.dbmap.DBConnectionType;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.introspection.exceptions.AAIUnmarshallingException;
+import org.openecomp.aai.logging.ErrorObjectNotFoundException;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.rest.db.DBRequest;
+import org.openecomp.aai.rest.db.HttpEntry;
+import org.openecomp.aai.rest.util.ValidateEncoding;
+import org.openecomp.aai.restcore.HttpMethod;
+import org.openecomp.aai.restcore.RESTAPI;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The Class BulkAddConsumer.
+ */
+/*
+ * The purpose of this endpoint is to allow a client to add
+ * multiple objects with one request. It may take
+ * one or more transaction objects containing one or more
+ * objects to add.
+ * The transactions are independent of each other -
+ * if one fails, its effects are rolled back, but the others' aren't.
+ * Within a single transaction, if adding one object fails, all the others'
+ * changes are rolled back.
+ */
+public abstract class BulkConsumer extends RESTAPI {
+
+ /** The introspector factory type. */
+ private ModelType introspectorFactoryType = ModelType.MOXY;
+
+ /** The query style. */
+ private QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+
+ /**
+ * Bulk add.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PUT
+ @Consumes({ MediaType.APPLICATION_JSON})
+ @Produces({ MediaType.APPLICATION_JSON})
+ public Response bulkAdd(String content, @PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req){
+
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String realTime = headers.getRequestHeaders().getFirst("Real-Time");
+ String outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
+ Version version = Version.valueOf(versionParam);
+ DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime);
+
+ Response response = null;
+
+ /* A Response will be generated for each object in each transaction.
+ * To keep track of what came from where to give organized feedback to the client,
+ * we keep responses from a given transaction together in one list (hence all being a list of lists)
+ * and pair each response with its matching URI (which will be null if there wasn't one).
+ */
+ List<List<Pair<URI, Response>>> allResponses = new ArrayList<List<Pair<URI, Response>>>();
+
+ try {
+ //TODO add auth check when this endpoint added to that auth properties files
+
+
+ JsonArray transactions = getTransactions(content);
+
+ for (int i = 0; i < transactions.size(); i++){
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type);
+ Loader loader = httpEntry.getLoader();
+ TransactionalGraphEngine dbEngine = httpEntry.getDbEngine();
+ URI thisUri = null;
+ List<Triplet<URI, Introspector,HttpMethod>> triplet = new ArrayList<Triplet<URI, Introspector,HttpMethod>>();
+ HttpMethod method = null;
+ try {
+ JsonElement transObj = transactions.get(i);
+ if (!(transObj instanceof JsonObject)) {
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+ //JsonObject transaction = transObj.getAsJsonObject();
+
+ fillObjectTuplesFromTransaction(triplet, transObj.getAsJsonObject(), loader, dbEngine, outputMediaType);
+ if (triplet.size() == 0) {
+ //case where user sends a validly formatted transactions object but
+ //which has no actual things in it for A&AI to do anything with
+ //assuming we should count this as a user error
+ throw new AAIException("AAI_6118", "payload had no objects to operate on");
+ }
+
+ List<DBRequest> requests = new ArrayList<>();
+ for (Triplet<URI, Introspector, HttpMethod> tuple : triplet){
+ thisUri = tuple.getValue0();
+ method = tuple.getValue2();
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(thisUri);
+ DBRequest request = new DBRequest.Builder(method, thisUri, uriQuery, tuple.getValue1(), headers, info, transId).build();
+ requests.add(request);
+ }
+
+ Pair<Boolean, List<Pair<URI, Response>>> results = httpEntry.process(requests, sourceOfTruth, this.enableResourceVersion());
+ List<Pair<URI, Response>> responses = results.getValue1();
+ allResponses.add(responses);
+ if (results.getValue0()) { //everything was processed without error
+ dbEngine.commit();
+ } else { //something failed
+ dbEngine.rollback();
+ }
+ } catch (Exception e) {
+ /* While httpEntry.process handles its exceptions, exceptions thrown in earlier helpers
+ * bubbles up to here. As we want to tie error messages to the URI of the object that caused
+ * them, we catch here, generate a Response, bundle it with that URI, and move on.
+ */
+ method = HttpMethod.PUT;
+ if (triplet.size() != 0) { //failed somewhere in the middle of tuple-filling
+ Triplet<URI, Introspector, HttpMethod> lastTuple = triplet.get(triplet.size()-1); //last one in there was the problem
+ if (lastTuple.getValue1() == null){
+ //failed out before thisUri could be set but after tuples started being filled
+ thisUri = lastTuple.getValue0();
+ method = lastTuple.getValue2();
+ }
+ } //else failed out on empty payload so tuples never filled (or failed out even earlier than tuple-filling)
+ addExceptionCaseFailureResponse(allResponses, e, i, thisUri, headers, info, method);
+ dbEngine.rollback();
+ continue; /* if an exception gets thrown within a transaction we want to keep going to
+ the next transaction, not break out of the whole request */
+ }
+ }
+
+ String returnPayload = generateResponsePayload(allResponses);
+
+ //unless a top level error gets thrown, we want to 201 bc the client wanted a "fire and forget" kind of setup
+ response = Response
+ .status(Status.CREATED)
+ .entity(returnPayload)
+ .build();
+ } catch (AAIException e) { //these catches needed for handling top level errors in payload parsing where the whole request must fail out
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e);
+ } catch(JsonSyntaxException e) {
+ AAIException ex = new AAIException("AAI_6111");
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex);
+ } catch (Exception e ) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, ex);
+ }
+
+ return response;
+ }
+
+
+ /**
+ * Gets the transactions.
+ *
+ * @param content - input JSON payload string
+ * @return JsonArray - the array of transactions
+ * @throws AAIException the AAI exception
+ * @throws JsonSyntaxException Parses and breaks the single payload into an array of individual transaction
+ * bodies to be processed.
+ */
+ private JsonArray getTransactions(String content) throws AAIException, JsonSyntaxException {
+ JsonParser parser = new JsonParser();
+
+ JsonObject input = parser.parse(content).getAsJsonObject();
+
+ if (!(input.has("transactions"))) {
+ throw new AAIException("AAI_6118", "input payload does not follow bulk add interface - missing \"transactions\"");
+ }
+ JsonElement transactionsObj = input.get("transactions");
+
+ if (!(transactionsObj.isJsonArray())){
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+ JsonArray transactions = transactionsObj.getAsJsonArray();
+ if (transactions.size() == 0) {
+ //case where user sends a validly formatted transactions object but
+ //which has no actual things in it for A&AI to do anything with
+ //assuming we should count this as a user error
+ throw new AAIException("AAI_6118", "payload had no objects to operate on");
+ }
+ return transactions;
+ }
+
+ /**
+ * Fill object tuples from transaction.
+ *
+ * @param tuples the tuples
+ * @param transaction - JSON body containing the objects to be added
+ * each object must have a URI and an object body
+ * @param loader the loader
+ * @param dbEngine the db engine
+ * @param inputMediaType the input media type
+ * @return list of tuples containing each introspector-wrapped object and its given URI
+ * @throws AAIException the AAI exception
+ * @throws JsonSyntaxException the json syntax exception
+ * @throws UnsupportedEncodingException Walks through the given transaction and unmarshals each object in it, then bundles each
+ * with its URI.
+ */
+ private void fillObjectTuplesFromTransaction(List<Triplet<URI, Introspector, HttpMethod>> triplet,
+ JsonObject transaction, Loader loader, TransactionalGraphEngine dbEngine, String inputMediaType)
+ throws AAIException, JsonSyntaxException, UnsupportedEncodingException {
+
+
+ if (transaction.has("put") && this.functionAllowed(HttpMethod.PUT)) {
+ pairUp(triplet, transaction, loader, dbEngine, inputMediaType, HttpMethod.PUT);
+ }
+ else if (transaction.has("delete") && this.functionAllowed(HttpMethod.DELETE)) {
+ pairUp(triplet, transaction, loader, dbEngine, inputMediaType, HttpMethod.DELETE);
+ }
+ else if (transaction.has("patch") && this.functionAllowed(HttpMethod.MERGE_PATCH)) {
+ pairUp(triplet, transaction, loader, dbEngine, inputMediaType, HttpMethod.MERGE_PATCH);
+ }
+
+ else{
+
+ throw new AAIException("AAI_6118", "input payload does not follow bulk add interface - missing put delete or patch");
+ }
+
+
+
+ }
+
+
+
+ private void pairUp(List<Triplet<URI, Introspector, HttpMethod>> triplet, JsonObject item, Loader loader, TransactionalGraphEngine dbEngine, String inputMediaType, HttpMethod method) throws AAIException, JsonSyntaxException, UnsupportedEncodingException{
+
+
+ for (int i=0; i<item.size(); i++) {
+ Triplet<URI, Introspector, HttpMethod> tuple = Triplet.with(null, null,null);
+
+ tuple = tuple.setAt2(method);
+ try {
+ if (!(item.isJsonObject())) {
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+
+
+ JsonElement actionElement = null;
+
+ if(item.has("put")){
+ actionElement = item.get("put");
+ } else if(item.has("patch")){
+ actionElement = item.get("patch");
+ } else if(item.has("delete")){
+ actionElement = item.get("delete");
+ }
+
+ if (!actionElement.isJsonArray()) {
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+ JsonArray httpArray = actionElement.getAsJsonArray();
+ for(int j = 0; j < httpArray.size(); ++j){
+ JsonObject it = httpArray.get(j).getAsJsonObject();
+ JsonElement itemURIfield = it.get("uri");
+ if (itemURIfield == null) {
+ throw new AAIException("AAI_6118", "must include object uri");
+ }
+ String uriStr = itemURIfield.getAsString();
+ if (uriStr.endsWith("/relationship-list/relationship")) {
+ if (method.equals(HttpMethod.PUT)) {
+ tuple = tuple.setAt2(HttpMethod.PUT_EDGE);
+ } else if (method.equals(HttpMethod.DELETE)) {
+ tuple = tuple.setAt2(HttpMethod.DELETE_EDGE);
+ }
+ } else {
+ tuple = tuple.setAt2(method);
+ }
+
+ URI uri = UriBuilder.fromPath(uriStr).build();
+
+ /* adding the uri as soon as we have one (valid or not) lets us
+ * keep any errors with their corresponding uris for client feedback
+ */
+ tuple = tuple.setAt0(uri);
+
+ if (!ValidateEncoding.getInstance().validate(uri)) {
+ throw new AAIException("AAI_3008", "uri=" + uri.getPath());
+ }
+
+ if (!(it.has("body"))){
+ throw new AAIException("AAI_6118", "input payload does not follow bulk add interface - missing \"body\"");
+ }
+ JsonElement bodyObj = it.get("body");
+ if (!(bodyObj.isJsonObject())) {
+ throw new AAIException("AAI_6111", "input payload does not follow bulk add interface");
+ }
+
+ Gson gson = new Gson();
+
+ String bodyStr = gson.toJson(bodyObj);
+
+ if (tuple.getValue2().equals(HttpMethod.PUT_EDGE)) {
+ Introspector obj;
+ try {
+ obj = loader.unmarshal("relationship", bodyStr, org.openecomp.aai.restcore.MediaType.getEnum(inputMediaType));
+ } catch (AAIUnmarshallingException e) {
+ throw new AAIException("AAI_3000", "object could not be unmarshalled:" + bodyStr);
+
+ }
+
+
+ tuple = tuple.setAt1(obj);
+
+ } else {
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uri);
+ String objName = uriQuery.getResultType();
+
+ Introspector obj;
+ try {
+ obj = loader.unmarshal(objName, bodyStr, org.openecomp.aai.restcore.MediaType.getEnum(inputMediaType));
+ } catch (AAIUnmarshallingException e) {
+ throw new AAIException("AAI_3000", "object could not be unmarshalled:" + bodyStr);
+
+ }
+
+ this.validateIntrospector(obj, loader, uri, tuple.getValue2());
+ tuple = tuple.setAt1(obj);
+ }
+ triplet.add(tuple);
+ }
+// JsonElement itemURIfield = item.get("uri");
+
+ } catch (AAIException e) {
+ // even if tuple doesn't have a uri or body, this way we keep all information associated with this error together
+ // even if both are null, that indicates how the input was messed up, so still useful to carry around like this
+ triplet.add(tuple);
+ throw e; //rethrow so the right response is generated on the level above
+ }
+ }
+ }
+
+
+
+ /**
+ * Generate response payload.
+ *
+ * @param allResponses - the list of the lists of responses from every action in every transaction requested
+ * @return A json string of similar format to the bulk add interface which for each response includes
+ * the original URI and a body with the status code of the response and the error message.
+ *
+ * Creates the payload for a single unified response from all responses generated
+ */
+ private String generateResponsePayload(List<List<Pair<URI,Response>>> allResponses){
+ JsonObject ret = new JsonObject();
+ JsonArray retArr = new JsonArray();
+
+ for(List<Pair<URI,Response>> responses : allResponses){
+ JsonObject tResp = new JsonObject();
+ JsonArray tArrResp = new JsonArray();
+
+ for (Pair<URI,Response> r : responses) {
+ JsonObject indPayload = new JsonObject();
+
+ URI origURI = r.getValue0();
+ if (origURI != null) {
+ indPayload.addProperty("uri", origURI.getPath());
+ } else {
+ indPayload.addProperty("uri", (String)null);
+ }
+
+ JsonObject body = new JsonObject();
+
+ int rStatus = r.getValue1().getStatus();
+ String rContents = null;
+
+ rContents = (String)r.getValue1().getEntity();
+
+ body.addProperty(new Integer(rStatus).toString(), rContents);
+ indPayload.add("body", body);
+
+ tArrResp.add(indPayload);
+ }
+
+ tResp.add("put", tArrResp);
+ retArr.add(tResp);
+ }
+ ret.add("transaction", retArr);
+ Gson gson = new GsonBuilder().serializeNulls().create();
+ String jsonStr = gson.toJson(ret);
+ return jsonStr;
+ }
+
+ /**
+ * Adds the exception case failure response.
+ *
+ * @param allResponses the all responses
+ * @param e the e
+ * @param index - index of which transaction was being processed when the exception was thrown
+ * @param thisUri the this uri
+ * @param headers the headers
+ * @param info the info
+ * @param templateAction the template action
+ * @param logline Generates a Response based on the given exception and adds it to the collection of responses for this request.
+ * @throws ErrorObjectNotFoundException
+ */
+ private void addExceptionCaseFailureResponse(List<List<Pair<URI, Response>>> allResponses, Exception e, int index, URI thisUri, HttpHeaders headers, UriInfo info, HttpMethod templateAction) {
+ AAIException ex = null;
+
+ if (!(e instanceof AAIException)){
+ ex = new AAIException("AAI_4000", e);
+ } else {
+ ex = (AAIException)e;
+ }
+
+ if (allResponses.size() != (index+1)) {
+ //index+1 bc if all transactions thus far have had a response list added
+ //the size will be one more than the current index (since those are offset by 1)
+
+ //this transaction doesn't have a response list yet, so create one
+ Response failResp = consumerExceptionResponseGenerator(headers, info, templateAction, ex);
+ Pair<URI, Response> uriResp = Pair.with(thisUri, failResp);
+ List<Pair<URI, Response>> transRespList = new ArrayList<Pair<URI,Response>>();
+ transRespList.add(uriResp);
+ allResponses.add(transRespList);
+ } else {
+ //this transaction already has a response list, so add this failure response to it
+ Response failResp = consumerExceptionResponseGenerator(headers, info, templateAction, ex);
+ Pair<URI, Response> uriResp = Pair.with(thisUri, failResp);
+ List<Pair<URI, Response>> tResps = allResponses.get(index);
+ tResps.add(uriResp);
+ }
+ }
+
+ protected abstract boolean functionAllowed(HttpMethod method);
+
+ protected abstract boolean enableResourceVersion();
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/BulkProcessConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/BulkProcessConsumer.java
new file mode 100644
index 0000000..91867ef
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/BulkProcessConsumer.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest;
+
+import javax.ws.rs.Path;
+
+import org.openecomp.aai.restcore.HttpMethod;
+
+@Path("{version: v[2789]|v1[0]}/bulkprocess")
+public class BulkProcessConsumer extends BulkConsumer {
+
+ @Override
+ protected boolean functionAllowed(HttpMethod method) {
+
+ return method.equals(HttpMethod.PUT) || method.equals(HttpMethod.DELETE) || method.equals(HttpMethod.MERGE_PATCH);
+ }
+
+ @Override
+ protected boolean enableResourceVersion() {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java
new file mode 100644
index 0000000..de59955
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/ExampleConsumer.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.MarshallerProperties;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.introspection.generator.CreateExample;
+import org.openecomp.aai.restcore.HttpMethod;
+import org.openecomp.aai.restcore.RESTAPI;
+
+/**
+ * The Class ExampleConsumer.
+ */
+@Path("/{version: v[2789]|v1[0]}/examples")
+public class ExampleConsumer extends RESTAPI {
+
+
+ /**
+ * Gets the example.
+ *
+ * @param versionParam the version param
+ * @param type the type
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the example
+ */
+ @GET
+ @Path("/{objectType: [^\\/]+}")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response getExample(@PathParam("version")String versionParam, @PathParam("objectType")String type, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ Status status = Status.INTERNAL_SERVER_ERROR;
+ Response response = null;
+
+ try {
+ String mediaType = getMediaType(headers.getAcceptableMediaTypes());
+ org.openecomp.aai.restcore.MediaType outputMediaType = org.openecomp.aai.restcore.MediaType.getEnum(mediaType);
+
+ Version version = Version.valueOf(versionParam);
+ Loader loader = LoaderFactory.createLoaderForVersion(ModelType.MOXY, version);
+
+ CreateExample example = new CreateExample(loader, type);
+
+ Introspector obj = example.getExampleObject();
+ String result = "";
+ if (obj != null) {
+ status = Status.OK;
+ MarshallerProperties properties =
+ new MarshallerProperties.Builder(outputMediaType).build();
+ result = obj.marshal(properties);
+ } else {
+
+ }
+ response = Response
+ .ok(obj)
+ .entity(result)
+ .status(status)
+ .type(outputMediaType.toString()).build();
+ } catch (AAIException e) {
+ //TODO check that the details here are sensible
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e);
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex);
+ }
+ return response;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java b/aai-resources/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java
new file mode 100644
index 0000000..f1a6f47
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/ExceptionHandler.java
@@ -0,0 +1,129 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.sun.istack.SAXParseException2;
+
+/**
+ * The Class ExceptionHandler.
+ */
+@Provider
+public class ExceptionHandler implements ExceptionMapper<Exception> {
+
+ @Context
+ private HttpServletRequest request;
+
+ @Context
+ private HttpHeaders headers;
+
+ /**
+ * @{inheritDoc}
+ */
+ @Override
+ public Response toResponse(Exception exception) {
+
+ Response response = null;
+ ArrayList<String> templateVars = new ArrayList<String>();
+
+ //the general case is that cxf will give us a WebApplicationException
+ //with a linked exception
+ if (exception instanceof WebApplicationException) {
+ WebApplicationException e = (WebApplicationException) exception;
+ if (e.getCause() != null) {
+ if (e.getCause() instanceof SAXParseException2) {
+ templateVars.add("UnmarshalException");
+ AAIException ex = new AAIException("AAI_4007", exception);
+ response = Response
+ .status(400)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars))
+ .build();
+ }
+ }
+ } else if (exception instanceof JsonParseException) {
+ //jackson does it differently so we get the direct JsonParseException
+ templateVars.add("JsonParseException");
+ AAIException ex = new AAIException("AAI_4007", exception);
+ response = Response
+ .status(400)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars))
+ .build();
+ } else if (exception instanceof JsonMappingException) {
+ //jackson does it differently so we get the direct JsonParseException
+ templateVars.add("JsonMappingException");
+ AAIException ex = new AAIException("AAI_4007", exception);
+ response = Response
+ .status(400)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars))
+ .build();
+ }
+
+ // it didn't get set above, we wrap a general fault here
+ if (response == null) {
+
+ Exception actual_e = exception;
+ if (exception instanceof WebApplicationException) {
+ WebApplicationException e = (WebApplicationException) exception;
+ response = e.getResponse();
+ } else {
+ templateVars.add(request.getMethod());
+ templateVars.add("unknown");
+ AAIException ex = new AAIException("AAI_4000", actual_e);
+ List<MediaType> mediaTypes = headers.getAcceptableMediaTypes();
+ int setError = 0;
+
+ for (MediaType mediaType : mediaTypes) {
+ if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) {
+ response = Response
+ .status(400)
+ .type(MediaType.APPLICATION_XML_TYPE)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars))
+ .build();
+ setError = 1;
+ }
+ }
+ if (setError == 0) {
+ response = Response
+ .status(400)
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), ex, templateVars))
+ .build();
+ }
+ }
+ }
+ return response;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java
new file mode 100644
index 0000000..7af432d
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java
@@ -0,0 +1,583 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.cxf.jaxrs.ext.PATCH;
+import org.javatuples.Pair;
+
+import org.openecomp.aai.dbmap.DBConnectionType;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.rest.db.DBRequest;
+import org.openecomp.aai.rest.db.HttpEntry;
+import org.openecomp.aai.rest.util.ValidateEncoding;
+import org.openecomp.aai.restcore.HttpMethod;
+import org.openecomp.aai.restcore.RESTAPI;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import org.openecomp.aai.workarounds.RemoveDME2QueryParams;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.common.base.Joiner;
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+
+/**
+ * The Class LegacyMoxyConsumer.
+ */
+@Path("{version: v[2789]|v1[0]}")
+public class LegacyMoxyConsumer extends RESTAPI {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(LegacyMoxyConsumer.class.getName());
+ protected static String authPolicyFunctionName = "REST";
+ private ModelType introspectorFactoryType = ModelType.MOXY;
+ private QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+
+ /**
+ * Update.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PUT
+ @Path("/{uri: .+}")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response update (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ MediaType mediaType = headers.getMediaType();
+
+ return this.handleWrites(Action.PUT, mediaType, HttpMethod.PUT, content, versionParam, uri, headers, info, req);
+ }
+
+ /**
+ * Update relationship.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PUT
+ @Path("/{uri: .+}/relationship-list/relationship")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response updateRelationship (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String realTime = headers.getRequestHeaders().getFirst("Real-Time");
+ MediaType inputMediaType = headers.getMediaType();
+ Response response = null;
+ Loader loader = null;
+ TransactionalGraphEngine dbEngine = null;
+ TitanTransaction g = null;
+ boolean success = true;
+
+ try {
+ validateRequest(info);
+ Version version = Version.valueOf(versionParam);
+ version = Version.valueOf(versionParam);
+ DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type);
+ loader = httpEntry.getLoader();
+ dbEngine = httpEntry.getDbEngine();
+
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
+
+ Introspector wrappedEntity = loader.unmarshal("relationship", content, org.openecomp.aai.restcore.MediaType.getEnum(this.getInputMediaType(inputMediaType)));
+
+ DBRequest request = new DBRequest.Builder(HttpMethod.PUT_EDGE, uriObject, uriQuery, wrappedEntity, headers, info, transId).build();
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+ success = responsesTuple.getValue0();
+
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, e);
+ success = false;
+ } catch (Exception e) {
+ AAIException aaiException = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.PUT, aaiException);
+ success = false;
+ } finally {
+ if (dbEngine != null) {
+ if (success) {
+ dbEngine.commit();
+ } else {
+ LOGGER.warn("Rolling back Titan transaction");
+ dbEngine.rollback();
+ }
+ }
+
+ }
+
+ return response;
+ }
+
+ /**
+ * Patch.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PATCH
+ @Path("/{uri: .+}")
+ @Consumes({ "application/merge-patch+json" })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response patch (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ MediaType mediaType = MediaType.APPLICATION_JSON_TYPE;
+
+ return this.handleWrites(Action.PUT, mediaType, HttpMethod.MERGE_PATCH, content, versionParam, uri, headers, info, req);
+
+ }
+
+ /**
+ * Gets the legacy.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param depthParam the depth param
+ * @param cleanUp the clean up
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the legacy
+ */
+ @GET
+ @Path("/{uri: .+}")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response getLegacy (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @DefaultValue("all") @QueryParam("depth") String depthParam, @DefaultValue("false") @QueryParam("cleanup") String cleanUp, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ return this.getLegacy(content, versionParam, uri, depthParam, cleanUp, headers, info, req, new HashSet<String>());
+ }
+
+ /**
+ * This method exists as a workaround for filtering out undesired query params while routing between REST consumers
+ *
+ * @param content
+ * @param versionParam
+ * @param uri
+ * @param depthParam
+ * @param cleanUp
+ * @param headers
+ * @param info
+ * @param req
+ * @param removeQueryParams
+ * @return
+ */
+ public Response getLegacy(String content, String versionParam, String uri, String depthParam, String cleanUp, HttpHeaders headers, UriInfo info, HttpServletRequest req, Set<String> removeQueryParams) {
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String realTime = headers.getRequestHeaders().getFirst("Real-Time");
+ Response response = null;
+ TransactionalGraphEngine dbEngine = null;
+ TitanTransaction g = null;
+ Loader loader = null;
+
+ try {
+ validateRequest(info);
+ Version version = Version.valueOf(versionParam);
+ DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime);
+ final HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type);
+ dbEngine = httpEntry.getDbEngine();
+ loader = httpEntry.getLoader();
+ MultivaluedMap<String, String> params = info.getQueryParameters();
+
+ RemoveDME2QueryParams dme2Workaround = new RemoveDME2QueryParams();
+ //clear out all params not used for filtering
+ params.remove("depth");
+ params.remove("cleanup");
+ params.remove("nodes-only");
+ for (String queryParam : removeQueryParams) {
+ params.remove(queryParam);
+ }
+ if (dme2Workaround.shouldRemoveQueryParams(params)) {
+ dme2Workaround.removeQueryParams(params);
+ }
+
+ uri = uri.split("\\?")[0];
+
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject, params);
+
+ String objType = "";
+ if (!uriQuery.getContainerType().equals("")) {
+ objType = uriQuery.getContainerType();
+ } else {
+ objType = uriQuery.getResultType();
+ }
+ Introspector obj = loader.introspectorFromName(objType);
+ DBRequest request =
+ new DBRequest.Builder(HttpMethod.GET, uriObject, uriQuery, obj, headers, info, transId).build();
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e);
+ } catch (Exception e ) {
+ AAIException ex = new AAIException("AAI_4000", e);
+
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex);
+ } finally {
+ if (dbEngine != null) {
+ if (cleanUp.equals("true")) {
+ dbEngine.commit();
+ } else {
+ dbEngine.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+ /**
+ * Delete.
+ *
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param resourceVersion the resource version
+ * @param req the req
+ * @return the response
+ */
+ @DELETE
+ @Path("/{uri: .+}")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response delete (@PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @QueryParam("resource-version")String resourceVersion, @Context HttpServletRequest req) {
+
+
+ String outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String realTime = headers.getRequestHeaders().getFirst("Real-Time");
+
+ TransactionalGraphEngine dbEngine = null;
+ Response response = Response.status(404)
+ .type(outputMediaType).build();
+
+ TitanTransaction g = null;
+ boolean success = true;
+
+ try {
+
+ validateRequest(info);
+ Version version = Version.valueOf(versionParam);
+ DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type);
+
+ dbEngine = httpEntry.getDbEngine();
+ Loader loader = httpEntry.getLoader();
+
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
+ String objType = uriQuery.getResultType();
+ Introspector obj = loader.introspectorFromName(objType);
+
+ DBRequest request = new DBRequest.Builder(HttpMethod.DELETE, uriObject, uriQuery, obj, headers, info, transId).build();
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+ success = responsesTuple.getValue0();
+
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, e);
+ success = false;
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, ex);
+ success = false;
+ } finally {
+ if (dbEngine != null) {
+ if (success) {
+ dbEngine.commit();
+ } else {
+ LOGGER.warn("Rolling back Titan transaction");
+ dbEngine.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+
+ /**
+ * This whole method does nothing because the body is being dropped while fielding the request.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @DELETE
+ @Path("/{uri: .+}/relationship-list/relationship")
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response deleteRelationship (String content, @PathParam("version")String versionParam, @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ MediaType inputMediaType = headers.getMediaType();
+
+ String outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String realTime = headers.getRequestHeaders().getFirst("Real-Time");
+
+ Loader loader = null;
+ TransactionalGraphEngine dbEngine = null;
+ Response response = Response.status(404)
+ .type(outputMediaType).build();
+
+ TitanTransaction g = null;
+ boolean success = true;
+
+ try {
+ this.validateRequest(info);
+ Version version = Version.valueOf(versionParam);
+ DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type);
+ loader = httpEntry.getLoader();
+ dbEngine = httpEntry.getDbEngine();
+
+ if (content.equals("")) {
+ throw new AAIException("AAI_3102", "You must supply a relationship");
+ }
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
+
+ Introspector wrappedEntity = loader.unmarshal("relationship", content, org.openecomp.aai.restcore.MediaType.getEnum(this.getInputMediaType(inputMediaType)));
+
+ DBRequest request = new DBRequest.Builder(HttpMethod.DELETE_EDGE, uriObject, uriQuery, wrappedEntity, headers, info, transId).build();
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+ success = responsesTuple.getValue0();
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, e);
+ success = false;
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.DELETE, ex);
+ success = false;
+ } finally {
+ if (dbEngine != null) {
+ if (success) {
+ dbEngine.commit();
+ } else {
+ LOGGER.warn("Rolling back Titan transaction");
+ dbEngine.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+
+ /**
+ * Validate request.
+ *
+ * @param uri the uri
+ * @param headers the headers
+ * @param req the req
+ * @param action the action
+ * @param info the info
+ * @throws AAIException the AAI exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private void validateRequest(UriInfo info) throws AAIException, UnsupportedEncodingException {
+
+ if (!ValidateEncoding.getInstance().validate(info)) {
+ throw new AAIException("AAI_3008", "uri=" + getPath(info));
+ }
+ }
+
+ /**
+ * Gets the path.
+ *
+ * @param info the info
+ * @return the path
+ */
+ private String getPath(UriInfo info) {
+ String path = info.getPath(false);
+ MultivaluedMap<String, String> map = info.getQueryParameters(false);
+ String params = "?";
+ List<String> parmList = new ArrayList<>();
+ for (String key : map.keySet()) {
+ for (String value : map.get(key)) {
+ parmList.add(key + "=" + value);
+ }
+ }
+ String queryParams = Joiner.on("&").join(parmList);
+ if (map.keySet().size() > 0) {
+ path += params + queryParams;
+ }
+
+ return path;
+
+ }
+
+ /**
+ * Handle writes.
+ *
+ * @param aaiAction the aai action
+ * @param mediaType the media type
+ * @param method the method
+ * @param content the content
+ * @param versionParam the version param
+ * @param uri the uri
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ private Response handleWrites(Action aaiAction, MediaType mediaType, HttpMethod method, String content, String versionParam, String uri, HttpHeaders headers, UriInfo info, HttpServletRequest req) {
+
+ Response response = null;
+ TransactionalGraphEngine dbEngine = null;
+ Loader loader = null;
+ Version version = null;
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String realTime = headers.getRequestHeaders().getFirst("Real-Time");
+ TitanTransaction g = null;
+ Boolean success = true;
+
+ try {
+
+ validateRequest(info);
+
+ version = Version.valueOf(versionParam);
+ DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type);
+ loader = httpEntry.getLoader();
+ dbEngine = httpEntry.getDbEngine();
+ URI uriObject = UriBuilder.fromPath(uri).build();
+
+ QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject);
+ String objName = uriQuery.getResultType();
+ if (content.length() == 0) {
+ if (mediaType.toString().contains(MediaType.APPLICATION_JSON)) {
+ content = "{}";
+ } else {
+ content = "<empty/>";
+ }
+ }
+ Introspector obj = loader.unmarshal(objName, content, org.openecomp.aai.restcore.MediaType.getEnum(this.getInputMediaType(mediaType)));
+ if (obj == null) {
+ throw new AAIException("AAI_3000", "object could not be unmarshalled:" + content);
+ }
+
+ this.validateIntrospector(obj, loader, uriObject, method);
+
+ DBRequest request =
+ new DBRequest.Builder(method, uriObject, uriQuery, obj, headers, info, transId)
+ .rawRequestContent(content).build();
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(requests, sourceOfTruth);
+
+ response = responsesTuple.getValue1().get(0).getValue1();
+ success = responsesTuple.getValue0();
+ } catch (AAIException e) {
+ response = consumerExceptionResponseGenerator(headers, info, method, e);
+ success = false;
+ } catch (Exception e ) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, method, ex);
+ success = false;
+ } finally {
+ if (dbEngine != null) {
+ if (success) {
+ dbEngine.commit();
+ } else {
+ LOGGER.warn("Rolling back Titan transaction");
+ dbEngine.rollback();
+ }
+ }
+ }
+
+ return response;
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java
new file mode 100644
index 0000000..d67a008
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/URLFromVertexIdConsumer.java
@@ -0,0 +1,120 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Iterator;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import org.openecomp.aai.dbmap.DBConnectionType;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.rest.db.HttpEntry;
+import org.openecomp.aai.restcore.HttpMethod;
+import org.openecomp.aai.restcore.RESTAPI;
+import org.openecomp.aai.serialization.db.DBSerializer;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import org.openecomp.aai.util.AAIConfig;
+import org.openecomp.aai.workarounds.LegacyURITransformer;
+
+/**
+ * The Class URLFromVertexIdConsumer.
+ */
+@Path("{version: v[2789]|v1[0]}/generateurl")
+public class URLFromVertexIdConsumer extends RESTAPI {
+ private ModelType introspectorFactoryType = ModelType.MOXY;
+ private QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+
+ private final String ID_ENDPOINT = "/id/{vertexid: \\d+}";
+
+ /**
+ * Generate url from vertex id.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param vertexid the vertexid
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @Path(ID_ENDPOINT)
+ @Produces({ MediaType.TEXT_PLAIN })
+ public Response generateUrlFromVertexId(String content, @PathParam("version")String versionParam, @PathParam("vertexid")long vertexid, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String realTime = headers.getRequestHeaders().getFirst("Real-Time");
+
+ Version version = Version.valueOf(versionParam);
+ StringBuilder result = new StringBuilder();
+ Response response = null;
+ TransactionalGraphEngine dbEngine = null;
+ try {
+ DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type);
+ dbEngine = httpEntry.getDbEngine();
+
+ DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth);
+
+ Iterator<Vertex> thisVertex = dbEngine.asAdmin().getTraversalSource().V(vertexid);
+
+ if (!thisVertex.hasNext()) {
+ throw new AAIException("AAI_6114", "no node at that vertex id");
+ }
+ URI uri = serializer.getURIForVertex(thisVertex.next());
+
+ result.append(uri.getRawPath());
+ result.insert(0, version);
+ result.insert(0, AAIConfig.get("aai.server.url.base"));
+ LegacyURITransformer urlTransformer = LegacyURITransformer.getInstance();
+ URI output = new URI(result.toString());
+
+ response = Response.ok().entity(result.toString()).status(Status.OK).type(MediaType.TEXT_PLAIN).build();
+ } catch (AAIException e) {
+ //TODO check that the details here are sensible
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e);
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex);
+ } finally { //to close the titan transaction (I think)
+ if (dbEngine != null) {
+ dbEngine.rollback();
+ }
+ }
+ return response;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java
new file mode 100644
index 0000000..9e1dcfc
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/VertexIdConsumer.java
@@ -0,0 +1,145 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.javatuples.Pair;
+
+import org.openecomp.aai.db.props.AAIProperties;
+import org.openecomp.aai.dbmap.DBConnectionType;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.MarshallerProperties;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.rest.db.DBRequest;
+import org.openecomp.aai.rest.db.HttpEntry;
+import org.openecomp.aai.restcore.HttpMethod;
+import org.openecomp.aai.restcore.RESTAPI;
+import org.openecomp.aai.serialization.db.DBSerializer;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+
+/**
+ * The Class VertexIdConsumer.
+ */
+@Path("{version: v[2789]|v1[0]}/resources")
+public class VertexIdConsumer extends RESTAPI {
+
+ private ModelType introspectorFactoryType = ModelType.MOXY;
+ private QueryStyle queryStyle = QueryStyle.TRAVERSAL;
+
+ private final String ID_ENDPOINT = "/id/{vertexid: \\d+}";
+
+ /**
+ * Gets the by vertex id.
+ *
+ * @param content the content
+ * @param versionParam the version param
+ * @param vertexid the vertexid
+ * @param depthParam the depth param
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the by vertex id
+ */
+ @GET
+ @Path(ID_ENDPOINT)
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response getByVertexId(String content, @PathParam("version")String versionParam, @PathParam("vertexid")long vertexid, @DefaultValue("all") @QueryParam("depth") String depthParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+
+ String outputMediaType = getMediaType(headers.getAcceptableMediaTypes());
+ String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId");
+ String transId = headers.getRequestHeaders().getFirst("X-TransactionId");
+ String realTime = headers.getRequestHeaders().getFirst("Real-Time");
+ Version version = Version.valueOf(versionParam);
+ Status status = Status.NOT_FOUND;
+ String result = "";
+ Response response = null;
+ TransactionalGraphEngine dbEngine = null;
+ try {
+ int depth = setDepth(depthParam);
+ DBConnectionType type = this.determineConnectionType(sourceOfTruth, realTime);
+ HttpEntry httpEntry = new HttpEntry(version, introspectorFactoryType, queryStyle, type);
+ dbEngine = httpEntry.getDbEngine();
+ Loader loader = httpEntry.getLoader();
+
+ DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth);
+
+ //get type of the object represented by the given id
+ Vertex thisVertex = null;
+ Iterator<Vertex> itr = dbEngine.asAdmin().getTraversalSource().V(vertexid);
+
+ if (!itr.hasNext()) {
+ throw new AAIException("AAI_6114", "no node at that vertex id");
+ }
+ thisVertex = itr.next();
+ String objName = thisVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
+
+ QueryParser query = dbEngine.getQueryBuilder(thisVertex).createQueryFromObjectName(objName);
+
+ Introspector obj = loader.introspectorFromName(query.getResultType());
+
+ URI uriObject = UriBuilder.fromPath(info.getPath()).build();
+
+ DBRequest request =
+ new DBRequest.Builder(HttpMethod.GET, uriObject, query, obj, headers, info, transId)
+ .customMarshaller(new MarshallerProperties.Builder(org.openecomp.aai.restcore.MediaType.getEnum(outputMediaType)).includeRoot(true).build()).build();
+
+ List<DBRequest> requests = new ArrayList<>();
+ requests.add(request);
+ Pair<Boolean, List<Pair<URI, Response>>> responsesTuple = httpEntry.process(requests, sourceOfTruth);
+ response = responsesTuple.getValue1().get(0).getValue1();
+ } catch (AAIException e){
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, e);
+ } catch (Exception e) {
+ AAIException ex = new AAIException("AAI_4000", e);
+ response = consumerExceptionResponseGenerator(headers, info, HttpMethod.GET, ex);
+ } finally { //to close the titan transaction (I think)
+ if (dbEngine != null) {
+ dbEngine.rollback();
+ }
+ }
+ return response;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/db/DBRequest.java b/aai-resources/src/main/java/org/openecomp/aai/rest/db/DBRequest.java
new file mode 100644
index 0000000..e7b6858
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/db/DBRequest.java
@@ -0,0 +1,251 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.db;
+
+import java.net.URI;
+import java.util.Optional;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
+
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.MarshallerProperties;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.restcore.HttpMethod;
+
+/**
+ * The Class DBRequest.
+ */
+public class DBRequest {
+
+ private final QueryParser parser;
+
+ private final Introspector introspector;
+
+ private final HttpHeaders headers;
+
+ private final String transactionId;
+
+ private final UriInfo info;
+
+ private final HttpMethod method;
+
+ private final URI uri;
+
+ private final Optional<String> rawRequestContent;
+
+ private final Optional<MarshallerProperties> marshallerProperties;
+
+
+ /**
+ * Instantiates a new DB request.
+ *
+ * @param method the method
+ * @param uri the uri
+ * @param parser the parser
+ * @param obj the obj
+ * @param headers the headers
+ * @param info the info
+ * @param transactionId the transaction id
+ */
+ private DBRequest(Builder builder) {
+ this.method = builder.getMethod();
+ this.parser = builder.getParser();
+ this.introspector = builder.getIntrospector();
+ this.headers = builder.getHeaders();
+ this.transactionId = builder.getTransactionId();
+ this.info = builder.getInfo();
+ this.uri = builder.getUri();
+ this.marshallerProperties = builder.getMarshallerProperties();
+ this.rawRequestContent = builder.getRawRequestContent();
+ }
+
+ /**
+ * Gets the headers.
+ *
+ * @return the headers
+ */
+ public HttpHeaders getHeaders() {
+ return headers;
+ }
+
+
+ /**
+ * Gets the transaction id.
+ *
+ * @return the transaction id
+ */
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ /**
+ * Gets the info.
+ *
+ * @return the info
+ */
+ public UriInfo getInfo() {
+ return info;
+ }
+
+ /**
+ * Gets the parser.
+ *
+ * @return the parser
+ */
+ public QueryParser getParser() {
+ return parser;
+ }
+
+ /**
+ * Gets the introspector.
+ *
+ * @return the introspector
+ */
+ public Introspector getIntrospector() {
+ return introspector;
+ }
+
+ /**
+ * Gets the method.
+ *
+ * @return the method
+ */
+ public HttpMethod getMethod() {
+ return method;
+ }
+
+ /**
+ * Gets the uri.
+ *
+ * @return the uri
+ */
+ public URI getUri() {
+ return uri;
+ }
+
+ /**
+ * Gets the raw content.
+ *
+ * @return the raw content
+ */
+ public Optional<String> getRawRequestContent() {
+ return rawRequestContent;
+ }
+
+ public Optional<MarshallerProperties> getMarshallerProperties() {
+ return marshallerProperties;
+ }
+
+
+
+ public static class Builder {
+
+ private QueryParser parser = null;
+
+ private Introspector introspector = null;
+
+ private HttpHeaders headers = null;
+
+ private String transactionId = null;
+
+ private UriInfo info = null;
+
+ private HttpMethod method = null;
+
+ private URI uri = null;
+
+ private Optional<MarshallerProperties> marshallerProperties = Optional.empty();
+
+ private Optional<String> rawRequestContent = Optional.empty();
+ /**
+ * Instantiates a new DB request.
+ *
+ * @param method the method
+ * @param uri the uri
+ * @param parser the parser
+ * @param obj the obj
+ * @param headers the headers
+ * @param info the info
+ * @param transactionId the transaction id
+ */
+ public Builder(HttpMethod method, URI uri, QueryParser parser, Introspector obj, HttpHeaders headers, UriInfo info, String transactionId) {
+ this.method = method;
+ this.parser = parser;
+ this.introspector = obj;
+ this.headers = headers;
+ this.transactionId = transactionId;
+ this.info = info;
+ this.uri = uri;
+
+ }
+
+ public QueryParser getParser() {
+ return parser;
+ }
+
+ public Introspector getIntrospector() {
+ return introspector;
+ }
+
+ public HttpHeaders getHeaders() {
+ return headers;
+ }
+
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ public UriInfo getInfo() {
+ return info;
+ }
+
+ public HttpMethod getMethod() {
+ return method;
+ }
+
+ public URI getUri() {
+ return uri;
+ }
+
+ public Builder customMarshaller(MarshallerProperties properties) {
+ this.marshallerProperties = Optional.of(properties);
+ return this;
+ }
+
+ public Builder rawRequestContent(String content) {
+ this.rawRequestContent = Optional.of(content);
+ return this;
+ }
+ protected Optional<MarshallerProperties> getMarshallerProperties() {
+ return marshallerProperties;
+ }
+ protected Optional<String> getRawRequestContent() {
+ return rawRequestContent;
+ }
+ public DBRequest build() {
+
+ return new DBRequest(this);
+ }
+
+
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java b/aai-resources/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java
new file mode 100644
index 0000000..ef305b0
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/db/HttpEntry.java
@@ -0,0 +1,570 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.db;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.core.UriBuilder;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.javatuples.Pair;
+
+import org.openecomp.aai.db.props.AAIProperties;
+import org.openecomp.aai.dbmap.DBConnectionType;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessage;
+import org.openecomp.aai.domain.responseMessage.AAIResponseMessageDatum;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.MarshallerProperties;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.introspection.ModelType;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.parsers.query.QueryParser;
+import org.openecomp.aai.parsers.uri.URIToExtensionInformation;
+import org.openecomp.aai.rest.ueb.UEBNotification;
+import org.openecomp.aai.restcore.HttpMethod;
+import org.openecomp.aai.schema.enums.ObjectMetadata;
+import org.openecomp.aai.serialization.db.DBSerializer;
+import org.openecomp.aai.serialization.engines.QueryStyle;
+import org.openecomp.aai.serialization.engines.TitanDBEngine;
+import org.openecomp.aai.serialization.engines.TransactionalGraphEngine;
+import org.openecomp.aai.serialization.engines.query.QueryEngine;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.fge.jsonpatch.JsonPatchException;
+import com.github.fge.jsonpatch.mergepatch.JsonMergePatch;
+import com.thinkaurelius.titan.core.TitanException;
+import com.thinkaurelius.titan.core.TitanTransaction;
+
+/**
+ * The Class HttpEntry.
+ */
+public class HttpEntry {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(HttpEntry.class);
+
+ private final ModelType introspectorFactoryType;
+
+ private final QueryStyle queryStyle;
+
+ private final Version version;
+
+ private final Loader loader;
+
+ private final TransactionalGraphEngine dbEngine;
+
+ private boolean processSingle = true;
+
+ /**
+ * Instantiates a new http entry.
+ *
+ * @param version the version
+ * @param modelType the model type
+ * @param queryStyle the query style
+ * @param llBuilder the ll builder
+ */
+ public HttpEntry(Version version, ModelType modelType, QueryStyle queryStyle, DBConnectionType connectionType) {
+ this.introspectorFactoryType = modelType;
+ this.queryStyle = queryStyle;
+ this.version = version;
+ this.loader = LoaderFactory.createLoaderForVersion(introspectorFactoryType, version);
+ this.dbEngine = new TitanDBEngine(
+ queryStyle,
+ connectionType,
+ loader);
+ //start transaction on creation
+ dbEngine.startTransaction();
+
+ }
+
+ /**
+ * Gets the introspector factory type.
+ *
+ * @return the introspector factory type
+ */
+ public ModelType getIntrospectorFactoryType() {
+ return introspectorFactoryType;
+ }
+
+ /**
+ * Gets the query style.
+ *
+ * @return the query style
+ */
+ public QueryStyle getQueryStyle() {
+ return queryStyle;
+ }
+
+ /**
+ * Gets the version.
+ *
+ * @return the version
+ */
+ public Version getVersion() {
+ return version;
+ }
+
+ /**
+ * Gets the loader.
+ *
+ * @return the loader
+ */
+ public Loader getLoader() {
+ return loader;
+ }
+
+ /**
+ * Gets the db engine.
+ *
+ * @return the db engine
+ */
+ public TransactionalGraphEngine getDbEngine() {
+ return dbEngine;
+ }
+
+ public Pair<Boolean, List<Pair<URI, Response>>> process (List<DBRequest> requests, String sourceOfTruth) throws AAIException {
+ return this.process(requests, sourceOfTruth, true);
+ }
+ /**
+ * Process.
+ * @param requests the requests
+ * @param sourceOfTruth the source of truth
+ *
+ * @return the pair
+ * @throws AAIException the AAI exception
+ */
+ public Pair<Boolean, List<Pair<URI, Response>>> process (List<DBRequest> requests, String sourceOfTruth, boolean enableResourceVersion) throws AAIException {
+ DBSerializer serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth);
+ Response response = null;
+ Status status = Status.NOT_FOUND;
+ Introspector obj = null;
+ QueryParser query = null;
+ URI uri = null;
+ String transactionId = null;
+ UEBNotification notification = new UEBNotification(loader);
+ int depth = AAIProperties.MAXIMUM_DEPTH;
+ List<Pair<URI,Response>> responses = new ArrayList<>();
+ MultivaluedMap<String, String> params = null;
+ HttpMethod method = null;
+ String uriTemp = "";
+ Boolean success = true;
+ QueryEngine queryEngine = dbEngine.getQueryEngine();
+ int maxRetries = 10;
+ int retry = 0;
+ for (DBRequest request : requests) {
+ try {
+ for (retry = 0; retry < maxRetries; ++retry) {
+ try {
+ method = request.getMethod();
+ obj = request.getIntrospector();
+ query = request.getParser();
+ transactionId = request.getTransactionId();
+ uriTemp = request.getUri().getRawPath().replaceFirst("^v\\d+/", "");
+ uri = UriBuilder.fromPath(uriTemp).build();
+ List<Vertex> vertices = query.getQueryBuilder().toList();
+ boolean isNewVertex = false;
+ String outputMediaType = getMediaType(request.getHeaders().getAcceptableMediaTypes());
+ String result = null;
+ params = request.getInfo().getQueryParameters(false);
+ depth = setDepth(obj, params.getFirst("depth"));
+ String cleanUp = params.getFirst("cleanup");
+ String requestContext = "";
+ List<String> requestContextList = request.getHeaders().getRequestHeader("aai-request-context");
+ if (requestContextList != null) {
+ requestContext = requestContextList.get(0);
+ }
+
+ if (cleanUp == null) {
+ cleanUp = "false";
+ }
+ if (vertices.size() > 1 && processSingle && !method.equals(HttpMethod.GET)) {
+ if (method.equals(HttpMethod.DELETE)) {
+ throw new AAIException("AAI_6138");
+ } else {
+ throw new AAIException("AAI_6137");
+ }
+ }
+ if (method.equals(HttpMethod.PUT)) {
+ String resourceVersion = (String)obj.getValue("resource-version");
+ if (vertices.size() == 1) {
+ if (enableResourceVersion) {
+ serializer.verifyResourceVersion("update", query.getResultType(), (String)vertices.get(0).<String>property("resource-version").orElse(null), resourceVersion, obj.getURI());
+ }
+ isNewVertex = false;
+ } else {
+ if (enableResourceVersion) {
+ serializer.verifyResourceVersion("create", query.getResultType(), "", resourceVersion, obj.getURI());
+ }
+ isNewVertex = true;
+ }
+ } else {
+ if (vertices.size() == 0) {
+ String msg = createNotFoundMessage(query.getResultType(), request.getUri());
+ throw new AAIException("AAI_6114", msg);
+ } else {
+ isNewVertex = false;
+ }
+ }
+ Vertex v = null;
+ if (!isNewVertex) {
+ v = vertices.get(0);
+ }
+ HashMap<String, Introspector> relatedObjects = new HashMap<>();
+ switch (method) {
+ case GET:
+ String nodeOnly = params.getFirst("nodes-only");
+ boolean isNodeOnly = nodeOnly != null;
+
+ obj = this.getObjectFromDb(vertices, serializer, query, obj, request.getUri(), depth, isNodeOnly, cleanUp);
+ if (obj != null) {
+ status = Status.OK;
+ MarshallerProperties properties;
+ if (!request.getMarshallerProperties().isPresent()) {
+ properties =
+ new MarshallerProperties.Builder(org.openecomp.aai.restcore.MediaType.getEnum(outputMediaType)).build();
+ } else {
+ properties = request.getMarshallerProperties().get();
+ }
+ result = obj.marshal(properties);
+ }
+
+ break;
+ case PUT:
+ if (isNewVertex) {
+ v = serializer.createNewVertex(obj);
+ } else {
+ serializer.touchStandardVertexProperties(v, false);
+ }
+ serializer.serializeToDb(obj, v, query, uri.getRawPath(), requestContext);
+ status = Status.OK;
+ if (isNewVertex) {
+ status = Status.CREATED;
+ }
+ obj = serializer.getLatestVersionView(v);
+ if (query.isDependent()) {
+ relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
+ }
+ notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects);
+
+ break;
+ case PUT_EDGE:
+ serializer.touchStandardVertexProperties(v, false);
+ serializer.createEdge(obj, v);
+ status = Status.OK;
+ break;
+ case MERGE_PATCH:
+ Introspector existingObj = (Introspector) obj.clone();
+ existingObj = this.getObjectFromDb(vertices, serializer, query, existingObj, request.getUri(), 0, false, cleanUp);
+ String existingJson = existingObj.marshal(false);
+ String newJson;
+
+ if (request.getRawRequestContent().isPresent()) {
+ newJson = request.getRawRequestContent().get();
+ } else {
+ newJson = "";
+ }
+ Object relationshipList = request.getIntrospector().getValue("relationship-list");
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ JsonNode existingNode = mapper.readTree(existingJson);
+ JsonNode newNode = mapper.readTree(newJson);
+ JsonMergePatch patch = JsonMergePatch.fromJson(newNode);
+ JsonNode completed = patch.apply(existingNode);
+ String patched = mapper.writeValueAsString(completed);
+ Introspector patchedObj = loader.unmarshal(existingObj.getName(), patched);
+ if (relationshipList == null) {
+ //if the caller didn't touch the relationship-list, we shouldn't either
+ patchedObj.setValue("relationship-list", null);
+ }
+ serializer.touchStandardVertexProperties(v, false);
+ serializer.serializeToDb(patchedObj, v, query, uri.getRawPath(), requestContext);
+ status = Status.OK;
+ patchedObj = serializer.getLatestVersionView(v);
+ if (query.isDependent()) {
+ relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
+ }
+ notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, patchedObj, relatedObjects);
+ } catch (IOException | JsonPatchException e) {
+ throw new AAIException("AAI_3000", "could not perform patch operation");
+ }
+ break;
+ case DELETE:
+ String resourceVersion = params.getFirst("resource-version");
+ obj = serializer.getLatestVersionView(v);
+ if (query.isDependent()) {
+ relatedObjects = this.getRelatedObjects(serializer, queryEngine, v);
+ }
+ serializer.delete(v, resourceVersion, enableResourceVersion);
+ status = Status.NO_CONTENT;
+ notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects);
+ break;
+ case DELETE_EDGE:
+ serializer.touchStandardVertexProperties(v, false);
+ serializer.deleteEdge(obj, v);
+ status = Status.NO_CONTENT;
+ break;
+ default:
+ break;
+ }
+
+
+ /* temporarily adding vertex id to the headers
+ * to be able to use for testing the vertex id endpoint functionality
+ * since we presently have no other way of generating those id urls
+ */
+ if (response == null && v != null && (
+ method.equals(HttpMethod.PUT)
+ || method.equals(HttpMethod.GET)
+ || method.equals(HttpMethod.MERGE_PATCH))
+ ) {
+ String myvertid = v.id().toString();
+ response = Response.status(status)
+ .header("vertex-id", myvertid)
+ .entity(result)
+ .type(outputMediaType).build();
+ } else if (response == null) {
+ response = Response.status(status)
+ .type(outputMediaType).build();
+ } else {
+ //response already set to something
+ }
+ Pair<URI,Response> pairedResp = Pair.with(request.getUri(), response);
+ responses.add(pairedResp);
+ //break out of retry loop
+ break;
+ } catch (TitanException e) {
+ this.dbEngine.rollback();
+ AAIException ex = new AAIException("AAI_6142", e);
+ ErrorLogHelper.logException(ex);
+ Thread.sleep((retry + 1) * 20);
+ this.dbEngine.startTransaction();
+ queryEngine = dbEngine.getQueryEngine();
+ serializer = new DBSerializer(version, dbEngine, introspectorFactoryType, sourceOfTruth);
+ }
+
+ if (retry == maxRetries) {
+ throw new AAIException("AAI_6134");
+ }
+ }
+ } catch (AAIException e) {
+ success = false;
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(request.getMethod().toString()); //GET, PUT, etc
+ templateVars.add(request.getUri().getPath().toString());
+ templateVars.addAll(e.getTemplateVars());
+
+ response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), e, templateVars))
+ .build();
+ Pair<URI,Response> pairedResp = Pair.with(request.getUri(), response);
+ responses.add(pairedResp);
+ continue;
+ } catch (Exception e) {
+ success = false;
+ e.printStackTrace();
+ AAIException ex = new AAIException("AAI_4000", e);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(request.getMethod().toString()); //GET, PUT, etc
+ templateVars.add(request.getUri().getPath().toString());
+
+ response = Response
+ .status(ex.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(request.getHeaders().getAcceptableMediaTypes(), ex, templateVars))
+ .build();
+ Pair<URI, Response> pairedResp = Pair.with(request.getUri(), response);
+ responses.add(pairedResp);
+ continue;
+ }
+ }
+
+ notification.triggerEvents();
+ Pair<Boolean, List<Pair<URI, Response>>> tuple = Pair.with(success, responses);
+ return tuple;
+ }
+
+ /**
+ * Gets the media type.
+ *
+ * @param mediaTypeList the media type list
+ * @return the media type
+ */
+ private String getMediaType(List <MediaType> mediaTypeList) {
+ String mediaType = MediaType.APPLICATION_JSON; // json is the default
+ for (MediaType mt : mediaTypeList) {
+ if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt)) {
+ mediaType = MediaType.APPLICATION_XML;
+ }
+ }
+ return mediaType;
+ }
+
+ /**
+ * Gets the object from db.
+ *
+ * @param serializer the serializer
+ * @param g the g
+ * @param query the query
+ * @param obj the obj
+ * @param uri the uri
+ * @param depth the depth
+ * @param cleanUp the clean up
+ * @return the object from db
+ * @throws AAIException the AAI exception
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws SecurityException the security exception
+ * @throws InstantiationException the instantiation exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ * @throws MalformedURLException the malformed URL exception
+ * @throws AAIUnknownObjectException
+ * @throws URISyntaxException
+ */
+ private Introspector getObjectFromDb(List<Vertex> results, DBSerializer serializer, QueryParser query, Introspector obj, URI uri, int depth, boolean nodeOnly, String cleanUp) throws AAIException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIUnknownObjectException, URISyntaxException {
+
+ //nothing found
+ if (results.size() == 0) {
+ String msg = createNotFoundMessage(query.getResultType(), uri);
+ throw new AAIException("AAI_6114", msg);
+ }
+
+ obj = serializer.dbToObject(results, obj, depth, nodeOnly, cleanUp);
+
+ return obj;
+ }
+
+
+ /**
+ * Creates the not found message.
+ *
+ * @param resultType the result type
+ * @param uri the uri
+ * @return the string
+ */
+ private String createNotFoundMessage(String resultType, URI uri) {
+
+ String msg = "No Node of type " + resultType + " found at: " + uri.getPath();
+
+ return msg;
+ }
+
+ /**
+ * Sets the depth.
+ *
+ * @param depthParam the depth param
+ * @return the int
+ * @throws AAIException the AAI exception
+ */
+ protected int setDepth(Introspector obj, String depthParam) throws AAIException {
+ int depth = AAIProperties.MAXIMUM_DEPTH;
+
+ if(depthParam == null){
+ if(this.version.compareTo(Version.v9) >= 0){
+ depth = 0;
+ } else {
+ depth = AAIProperties.MAXIMUM_DEPTH;
+ }
+ } else {
+ if (depthParam.length() > 0 && !depthParam.equals("all")){
+ try {
+ depth = Integer.valueOf(depthParam);
+ } catch (Exception e) {
+ throw new AAIException("AAI_4016");
+ }
+
+ }
+ }
+ String maxDepth = obj.getMetadata(ObjectMetadata.MAXIMUM_DEPTH);
+
+ int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
+
+ if(maxDepth != null){
+ try {
+ maximumDepth = Integer.parseInt(maxDepth);
+ } catch(Exception ex){
+ throw new AAIException("AAI_4018");
+ }
+ }
+
+ if(depth > maximumDepth){
+ throw new AAIException("AAI_3303");
+ }
+
+ return depth;
+ }
+
+ /**
+ * Checks if is modification method.
+ *
+ * @param method the method
+ * @return true, if is modification method
+ */
+ private boolean isModificationMethod(HttpMethod method) {
+ boolean result = false;
+
+ if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PUT_EDGE) || method.equals(HttpMethod.DELETE_EDGE) || method.equals(HttpMethod.MERGE_PATCH)) {
+ result = true;
+ }
+
+ return result;
+
+ }
+
+ private HashMap<String, Introspector> getRelatedObjects(DBSerializer serializer, QueryEngine queryEngine, Vertex v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, InstantiationException, NoSuchMethodException, UnsupportedEncodingException, AAIException, URISyntaxException {
+ HashMap<String, Introspector> relatedVertices = new HashMap<>();
+ List<Vertex> vertexChain = queryEngine.findParents(v);
+ for (Vertex vertex : vertexChain) {
+ try {
+ final Introspector vertexObj = serializer.getVertexProperties(vertex);
+ relatedVertices.put(vertexObj.getObjectId(), vertexObj);
+ } catch (AAIUnknownObjectException e) {
+ LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned");
+ }
+
+ }
+
+ return relatedVertices;
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/retired/RetiredConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/retired/RetiredConsumer.java
new file mode 100644
index 0000000..99974ef
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/retired/RetiredConsumer.java
@@ -0,0 +1,143 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.retired;
+
+import java.util.ArrayList;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.cxf.jaxrs.ext.PATCH;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.restcore.RESTAPI;
+import org.openecomp.aai.util.AAIConfig;
+
+/**
+ * The Class RetiredConsumer.
+ */
+public abstract class RetiredConsumer extends RESTAPI {
+
+ /**
+ * Creates the message get.
+ *
+ * @param versionParam the version param
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @GET
+ @Path("/{uri:.*}")
+ public Response createMessageGet(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+ return createMessage(versionParam, headers, info, req);
+ }
+
+ /**
+ * Creates the message delete.
+ *
+ * @param versionParam the version param
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @DELETE
+ @Path("/{uri:.*}")
+ public Response createMessageDelete(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+ return createMessage(versionParam, headers, info, req);
+ }
+
+ /**
+ * Creates the message post.
+ *
+ * @param versionParam the version param
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @POST
+ @Path("/{uri:.*}")
+ public Response createMessagePost(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+ return createMessage(versionParam, headers, info, req);
+ }
+
+ @PATCH
+ @Path("/{uri:.*}")
+ public Response createMessagePatch(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+ return createMessage(versionParam, headers, info, req);
+ }
+ /**
+ * Creates the message put.
+ *
+ * @param versionParam the version param
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ @PUT
+ @Path("/{uri:.*}")
+ public Response createMessagePut(@PathParam("version")String versionParam, @Context HttpHeaders headers, @Context UriInfo info, @Context HttpServletRequest req) {
+ return createMessage(versionParam, headers, info, req);
+ }
+
+
+ /**
+ * Creates the message.
+ *
+ * @param versionParam the version param
+ * @param headers the headers
+ * @param info the info
+ * @param req the req
+ * @return the response
+ */
+ private Response createMessage(String versionParam, HttpHeaders headers, UriInfo info, HttpServletRequest req) {
+ AAIException e = new AAIException("AAI_3007");
+
+ ArrayList<String> templateVars = new ArrayList<String>();
+
+ if (templateVars.size() == 0) {
+ templateVars.add("PUT");
+ templateVars.add(info.getPath().toString());
+ templateVars.add(versionParam);
+ templateVars.add(AAIConfig.get("aai.default.api.version", ""));
+ }
+
+ Response response = Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e,
+ templateVars)).build();
+
+ return response;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V3ThroughV7Consumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V3ThroughV7Consumer.java
new file mode 100644
index 0000000..5572586
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V3ThroughV7Consumer.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.retired;
+
+import javax.ws.rs.Path;
+
+@Path("{version: v[3-6]}") //TODO re-add v7 when we fix our env issues AAI-8567
+public class V3ThroughV7Consumer extends RetiredConsumer {
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java b/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java
new file mode 100644
index 0000000..389d296
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.ueb;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.util.StoreNotificationEvent;
+
+/**
+ * The Class NotificationEvent.
+ */
+public class NotificationEvent {
+
+ private Loader loader = null;
+
+ private Introspector eventHeader = null;
+
+ private Introspector obj = null;
+
+ /**
+ * Instantiates a new notification event.
+ *
+ * @param version the version
+ * @param eventHeader the event header
+ * @param obj the obj
+ */
+ public NotificationEvent (Loader loader, Introspector eventHeader, Introspector obj) {
+ this.loader = loader;
+ this.eventHeader = eventHeader;
+ this.obj = obj;
+ }
+
+ /**
+ * Trigger.
+ *
+ * @throws AAIException the AAI exception
+ */
+ public void trigger() throws AAIException {
+
+ StoreNotificationEvent sne = new StoreNotificationEvent();
+
+ sne.storeEvent(loader, eventHeader, obj);
+
+ }
+
+ /**
+ * Gets the notification version.
+ *
+ * @return the notification version
+ */
+ public Version getNotificationVersion() {
+ return loader.getVersion();
+ }
+
+ /**
+ * Gets the event header.
+ *
+ * @return the event header
+ */
+ public Introspector getEventHeader() {
+ return eventHeader;
+ }
+
+ /**
+ * Gets the obj.
+ *
+ * @return the obj
+ */
+ public Introspector getObj() {
+ return obj;
+ }
+
+
+
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java b/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java
new file mode 100644
index 0000000..397082f
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java
@@ -0,0 +1,178 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.ueb;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.openecomp.aai.db.props.AAIProperties;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.LoaderFactory;
+import org.openecomp.aai.introspection.Version;
+import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException;
+import org.openecomp.aai.introspection.exceptions.AAIUnmarshallingException;
+import org.openecomp.aai.parsers.uri.URIToObject;
+import org.openecomp.aai.util.AAIConfig;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * The Class UEBNotification.
+ */
+public class UEBNotification {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(UEBNotification.class);
+
+ private Loader currentVersionLoader = null;
+ protected List<NotificationEvent> events = null;
+ private String urlBase = null;
+ private Version notificationVersion = null;
+
+ /**
+ * Instantiates a new UEB notification.
+ *
+ * @param loader the loader
+ */
+ public UEBNotification(Loader loader) {
+ events = new ArrayList<>();
+ currentVersionLoader = LoaderFactory.createLoaderForVersion(loader.getModelType(), AAIProperties.LATEST);
+ urlBase = AAIConfig.get("aai.server.url.base","");
+ notificationVersion = Version.valueOf(AAIConfig.get("aai.notification.current.version","v10"));
+ }
+
+
+ /**
+ * Creates the notification event.
+ *
+ * @param transactionId the X-TransactionId
+ * @param sourceOfTruth
+ * @param status the status
+ * @param uri the uri
+ * @param obj the obj
+ * @throws AAIException the AAI exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public void createNotificationEvent(String transactionId, String sourceOfTruth, Status status, URI uri, Introspector obj, HashMap<String, Introspector> relatedObjects) throws AAIException, IllegalArgumentException, UnsupportedEncodingException {
+
+ String action = "UPDATE";
+
+ if (status.equals(Status.CREATED)) {
+ action = "CREATE";
+ } else if (status.equals(Status.OK)) {
+ action = "UPDATE";
+ } else if (status.equals(Status.NO_CONTENT)) {
+ action = "DELETE";
+ }
+
+ try {
+ Introspector eventHeader = currentVersionLoader.introspectorFromName("notification-event-header");
+ URIToObject parser = new URIToObject(currentVersionLoader, uri, relatedObjects);
+
+ String entityLink = "";
+ if (uri.toString().startsWith("/")) {
+ entityLink = urlBase + notificationVersion + uri;
+ } else {
+ entityLink = urlBase + notificationVersion + "/" + uri;
+ }
+
+
+ eventHeader.setValue("entity-link", entityLink);
+ eventHeader.setValue("action", action);
+ eventHeader.setValue("entity-type", obj.getDbName());
+ eventHeader.setValue("top-entity-type", parser.getTopEntityName());
+ eventHeader.setValue("source-name", sourceOfTruth);
+ eventHeader.setValue("version", notificationVersion.toString());
+ eventHeader.setValue("id", transactionId);
+
+ List<Object> parentList = parser.getParentList();
+ parentList.clear();
+
+ if (!parser.getTopEntity().equals(parser.getEntity())) {
+ Introspector child = obj;
+ if (!parser.getLoader().getVersion().equals(obj.getVersion())) {
+ String json = obj.marshal(false);
+ child = parser.getLoader().unmarshal(parser.getEntity().getName(), json);
+ }
+
+ //wrap the child object in its parents
+ parentList.add(child.getUnderlyingObject());
+ }
+
+ final Introspector eventObject;
+
+ //convert to most resent version
+ if (!parser.getLoader().getVersion().equals(currentVersionLoader.getVersion())) {
+ String json = "";
+ if (parser.getTopEntity().equals(parser.getEntity())) {
+ //convert the parent object passed in
+ json = obj.marshal(false);
+ eventObject = currentVersionLoader.unmarshal(obj.getName(), json);
+ } else {
+ //convert the object created in the parser
+ json = parser.getTopEntity().marshal(false);
+ eventObject = currentVersionLoader.unmarshal(parser.getTopEntity().getName(), json);
+ }
+ } else {
+ if (parser.getTopEntity().equals(parser.getEntity())) {
+ //take the top level parent object passed in
+ eventObject = obj;
+ } else {
+ //take the wrapped child objects (ogres are like onions)
+ eventObject = parser.getTopEntity();
+ }
+ }
+
+ final NotificationEvent event = new NotificationEvent(currentVersionLoader, eventHeader, eventObject);
+ events.add(event);
+ } catch (AAIUnknownObjectException e) {
+ throw new RuntimeException("Fatal error - notification-event-header object not found!");
+ } catch (AAIUnmarshallingException e) {
+ LOGGER.error("Unmarshalling error occurred while generating UEBNotification", e);
+ }
+ }
+
+ /**
+ * Trigger events.
+ *
+ * @throws AAIException the AAI exception
+ */
+ public void triggerEvents() throws AAIException {
+ for (NotificationEvent event : events) {
+ event.trigger();
+ }
+ events.clear();
+ }
+
+ public List<NotificationEvent> getEvents() {
+ return this.events;
+ }
+
+
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java b/aai-resources/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java
new file mode 100644
index 0000000..6d01435
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/util/EchoResponse.java
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import org.openecomp.aai.restcore.RESTAPI;
+
+/**
+ * The Class EchoResponse.
+ */
+public class EchoResponse extends RESTAPI {
+
+ protected static String authPolicyFunctionName = "util";
+
+ public static final String echoPath = "/util/echo";
+
+ /**
+ * Simple health-check API that echos back the X-FromAppId and X-TransactionId to clients.
+ * If there is a query string, a transaction gets logged into hbase, proving the application is connected to the data store.
+ * If there is no query string, no transacction logging is done to hbase.
+ *
+ * @param headers the headers
+ * @param req the req
+ * @param myAction if exists will cause transaction to be logged to hbase
+ * @return the response
+ */
+ @GET
+ @Produces( { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+ @Path(echoPath)
+ public Response echoResult(@Context HttpHeaders headers, @Context HttpServletRequest req,
+ @QueryParam("action") String myAction) {
+ Response response = null;
+
+ AAIException ex = null;
+ String fromAppId = null;
+ String transId = null;
+
+ try {
+ fromAppId = getFromAppId(headers );
+ transId = getTransId(headers);
+ } catch (AAIException e) {
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add("PUT uebProvider");
+ templateVars.add("addTopic");
+ return Response
+ .status(e.getErrorObject().getHTTPResponseCode())
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(headers.getAcceptableMediaTypes(), e, templateVars))
+ .build();
+ }
+
+ try {
+
+ HashMap<AAIException, ArrayList<String>> exceptionList = new HashMap<AAIException, ArrayList<String>>();
+
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(fromAppId);
+ templateVars.add(transId);
+
+ exceptionList.put(new AAIException("AAI_0002", "OK"), templateVars);
+
+ response = Response.status(Status.OK)
+ .entity(ErrorLogHelper.getRESTAPIInfoResponse(
+ headers.getAcceptableMediaTypes(), exceptionList))
+ .build();
+
+ } catch (Exception e) {
+ ex = new AAIException("AAI_4000", e);
+ ArrayList<String> templateVars = new ArrayList<String>();
+ templateVars.add(Action.GET.name());
+ templateVars.add(fromAppId +" "+transId);
+
+ response = Response
+ .status(Status.INTERNAL_SERVER_ERROR)
+ .entity(ErrorLogHelper.getRESTAPIErrorResponse(
+ headers.getAcceptableMediaTypes(), ex,
+ templateVars)).build();
+
+ } finally {
+ if (ex != null) {
+ ErrorLogHelper.logException(ex);
+ }
+
+ }
+
+ return response;
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/util/LogFormatTools.java b/aai-resources/src/main/java/org/openecomp/aai/rest/util/LogFormatTools.java
new file mode 100644
index 0000000..d6fcd67
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/util/LogFormatTools.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.util;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class LogFormatTools {
+
+ private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
+ private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern(DATE_FORMAT)
+ .withZone(ZoneOffset.UTC);
+
+ public static String getCurrentDateTime() {
+ return DTF.format(ZonedDateTime.now());
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java b/aai-resources/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java
new file mode 100644
index 0000000..a09a317
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/rest/util/ValidateEncoding.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.rest.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriInfo;
+
+import org.springframework.web.util.UriUtils;
+
+/**
+ * The Class ValidateEncoding.
+ */
+public class ValidateEncoding {
+
+ private final String encoding = "UTF-8";
+
+ /**
+ * Instantiates a new validate encoding.
+ */
+ private ValidateEncoding() {
+
+ }
+
+ /**
+ * The Class Helper.
+ */
+ private static class Helper {
+
+ /** The Constant INSTANCE. */
+ private static final ValidateEncoding INSTANCE = new ValidateEncoding();
+ }
+
+ /**
+ * Gets the single instance of ValidateEncoding.
+ *
+ * @return single instance of ValidateEncoding
+ */
+ public static ValidateEncoding getInstance() {
+ return Helper.INSTANCE;
+ }
+
+ /**
+ * Validate.
+ *
+ * @param uri the uri
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public boolean validate(URI uri) throws UnsupportedEncodingException {
+ boolean result = true;
+ if (!validatePath(uri.getRawPath())) {
+ result = false;
+ }
+ /*if (!validateQueryParams(uri.getRawQuery())) {
+ result = false;
+ } //TODO
+ */
+
+ return result;
+ }
+
+ /**
+ * Validate.
+ *
+ * @param info the info
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ public boolean validate(UriInfo info) throws UnsupportedEncodingException {
+ boolean result = true;
+ if (!validatePath(info.getPath(false))) {
+ result = false;
+ }
+ if (!validateQueryParams(info.getQueryParameters(false))) {
+ result = false;
+ }
+
+ return result;
+ }
+
+ /**
+ * Validate path.
+ *
+ * @param path the path
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private boolean validatePath(String path) throws UnsupportedEncodingException {
+ String[] segments = path.split("/");
+ boolean valid = true;
+ for (String segment : segments) {
+ if (!this.checkEncoding(segment)) {
+ valid = false;
+ }
+ }
+
+ return valid;
+
+ }
+
+ /**
+ * Validate query params.
+ *
+ * @param params the params
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private boolean validateQueryParams(MultivaluedMap<String, String> params) throws UnsupportedEncodingException {
+ boolean valid = true;
+
+ for (String key : params.keySet()) {
+ if (!this.checkEncoding(key)) {
+ valid = false;
+ }
+ for (String item : params.get(key)) {
+ if (!this.checkEncoding(item)) {
+ valid = false;
+ }
+ }
+ }
+ return valid;
+ }
+
+ /**
+ * Check encoding.
+ *
+ * @param segment the segment
+ * @return true, if successful
+ * @throws UnsupportedEncodingException the unsupported encoding exception
+ */
+ private boolean checkEncoding(String segment) throws UnsupportedEncodingException {
+ boolean result = false;
+ String decode = UriUtils.decode(segment, encoding);
+ String encode = UriUtils.encode(decode, encoding);
+ result = segment.equals(encode);
+
+ return result;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/transforms/Converter.java b/aai-resources/src/main/java/org/openecomp/aai/transforms/Converter.java
new file mode 100644
index 0000000..44a0222
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/transforms/Converter.java
@@ -0,0 +1,25 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.transforms;
+
+public interface Converter {
+ String convert(String input);
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/transforms/LowerCamelToLowerHyphenConverter.java b/aai-resources/src/main/java/org/openecomp/aai/transforms/LowerCamelToLowerHyphenConverter.java
new file mode 100644
index 0000000..a31da05
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/transforms/LowerCamelToLowerHyphenConverter.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.transforms;
+
+import com.google.common.base.CaseFormat;
+
+public class LowerCamelToLowerHyphenConverter implements Converter {
+
+ @Override
+ public String convert(String input) {
+ if(input == null){
+ return null;
+ }
+ return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, input);
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverter.java b/aai-resources/src/main/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverter.java
new file mode 100644
index 0000000..784adbe
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/transforms/LowerHyphenToLowerCamelConverter.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.transforms;
+
+/**
+ * <b>LowerHyphenToLowerCamelConverter</b> is the converter to use
+ * for converting from the lower hyphen to lower camel case
+ * <p>
+ * Examples:
+ * lower-test => lowerTest
+ * lower-Test => lowerTest
+ * lowerTest => lowerTest
+ * lower-test-val => lowerTestVal
+ * <p>
+ *
+ */
+public class LowerHyphenToLowerCamelConverter implements Converter {
+
+ /**
+ * Converts the dash formatted string into a camel case string
+ * Ensure that the capitalization is not lost during this conversion
+ * <p>
+ * Loops through each character in the string
+ * checks if the current character is '-' and if it is then sets the
+ * boolean isPreviousCharDash to true and continues to the next iteration
+ * If the character is not '-', then checks if the previous character is dash
+ * If it is, then it will upper case the current character and appends to the builder
+ * Otherwise, it will just append the current character without any modification
+ *
+ * @param input the input string to convert to camel case
+ * @return a string that is converted to camel case
+ * if the input is null, then it returns null
+ */
+ @Override
+ public String convert(String input) {
+ if(input == null){
+ return null;
+ }
+
+ int size = input.length();
+ StringBuilder builder = new StringBuilder(size);
+
+ boolean isPreviousCharDash = false;
+
+ for(int index = 0; index < size; ++index){
+ char ch = input.charAt(index);
+
+ if(ch == '-'){
+ isPreviousCharDash = true;
+ continue;
+ }
+ if(isPreviousCharDash){
+ builder.append(Character.toUpperCase(ch));
+ isPreviousCharDash = false;
+ } else{
+ builder.append(ch);
+ }
+ }
+
+ return builder.toString();
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/transforms/MapTraverser.java b/aai-resources/src/main/java/org/openecomp/aai/transforms/MapTraverser.java
new file mode 100644
index 0000000..7695240
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/transforms/MapTraverser.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.transforms;
+
+
+import joptsimple.internal.Objects;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MapTraverser {
+
+ private Converter converter;
+
+ public MapTraverser(Converter converter){
+ this.converter = converter;
+ }
+
+ public Map<String, Object> convertKeys(Map<String, Object> map){
+
+ Objects.ensureNotNull(map);
+
+ Map<String, Object> modifiedMap = new HashMap<String, Object>();
+ convertKeys(map, modifiedMap);
+
+ return modifiedMap;
+ }
+
+ private Map<String, Object> convertKeys(Map<String, Object> original, Map<String, Object> modified){
+
+ for(Map.Entry<String, Object> entry : original.entrySet()){
+ String key = entry.getKey();
+ key = converter.convert(key);
+ Object value = entry.getValue();
+ if(value instanceof Map){
+ modified.put(key, convertKeys((Map<String, Object>)value, new HashMap<String, Object>()));
+ } else if(value instanceof List){
+ modified.put(key, convertKeys((List<Object>) value));
+ } else {
+ modified.put(key, value);
+ }
+ }
+
+ return modified;
+ }
+
+ public List<Object> convertKeys(List<Object> list){
+
+ List<Object> modifiedList = new ArrayList<Object>();
+ if(list != null && list.size() > 0){
+
+ for(Object o : list){
+ if(o instanceof Map){
+ Map<String, Object> map = (Map<String, Object>) o;
+ modifiedList.add(convertKeys(map));
+ } else if(o instanceof List){
+ List<Object> l = (List<Object>) o;
+ modifiedList.add(convertKeys(l));
+ } else {
+ modifiedList.add(o);
+ }
+ }
+ }
+
+ return modifiedList;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java b/aai-resources/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java
new file mode 100644
index 0000000..773b4a6
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/util/AAIAppServletContextListener.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.util;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+//import org.apache.activemq.broker.BrokerService;
+
+import org.openecomp.aai.dbmap.AAIGraph;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.ModelInjestor;
+import org.openecomp.aai.logging.ErrorLogHelper;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+public class AAIAppServletContextListener implements ServletContextListener {
+
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(AAIAppServletContextListener.class.getName());
+
+ //private BrokerService broker = new BrokerService();
+
+ /**
+ * Destroys Context
+ *
+ * @param arg0 the ServletContextEvent
+ */
+ public void contextDestroyed(ServletContextEvent arg0) {
+ LOGGER.info("AAIGraph shutting down");
+ AAIGraph.getInstance().graphShutdown();
+ LOGGER.info("AAIGraph shutdown");
+
+ try {
+// broker.stop();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Initializes Context
+ *
+ * @param arg0 the ServletContextEvent
+ */
+ public void contextInitialized(ServletContextEvent arg0) {
+ System.setProperty("org.openecomp.aai.serverStarted", "false");
+ LOGGER.info("***AAI Server initialization started...");
+
+ try {
+ LOGGER.info("Loading aaiconfig.properties");
+ AAIConfig.init();
+
+ LOGGER.info("Loading error.properties");
+ ErrorLogHelper.loadProperties();
+
+ LOGGER.info("Loading graph database");
+
+ AAIGraph.getInstance();
+ ModelInjestor.getInstance();
+
+ // Jsm internal broker for aai events
+ //broker = new BrokerService();
+ //broker.addConnector("tcp://localhost:61447");
+ //broker.setPersistent(false);
+ //broker.setUseJmx(false);
+ //broker.setSchedulerSupport(false);
+ //broker.start();
+
+ LOGGER.info("A&AI Server initialization succcessful.");
+ System.setProperty("org.openecomp.aai.serverStarted", "true");
+
+ } catch (AAIException e) {
+ ErrorLogHelper.logException(e);
+ throw new RuntimeException("AAIException caught while initializing A&AI server", e);
+ } catch (IOException e) {
+ ErrorLogHelper.logError("AAI_4000", e.getMessage());
+ throw new RuntimeException("IOException caught while initializing A&AI server", e);
+ } catch (Exception e) {
+ LOGGER.error("Unknown failure while initializing A&AI Server", e);
+ throw new RuntimeException("Unknown failure while initializing A&AI server", e);
+ }
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java b/aai-resources/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java
new file mode 100644
index 0000000..dd72530
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/util/GenerateMethodMapper.java
@@ -0,0 +1,142 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.util;
+
+import java.io.FileWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.openecomp.aai.audit.ListEndpoints;
+import org.openecomp.aai.introspection.Version;
+
+public class GenerateMethodMapper {
+
+ private final static String filePath = "bundleconfig-local/etc/appprops/methodMapper.properties";
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ * @throws Exception the exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ ListEndpoints le = null;
+ JSONObject jo = new JSONObject();
+ JSONArray ja = new JSONArray();
+
+ for (Version version : Version.values()) {
+
+ le = new ListEndpoints(version);
+ Map<String, String> ln = le.getLogicalNames();
+ List<String> keys = new ArrayList<String>(ln.keySet());
+ Collections.sort(keys);
+ for (String key : keys) {
+ addEndpointToJsonArray(key, ln.get(key), ja, version.toString());
+ }
+
+ }
+
+ addUniqueEndpoints(ja);
+
+ jo.put("ActiveAndAvailableInventory-CloudNetwork", ja);
+ try (FileWriter file = new FileWriter(filePath)) {
+ file.write(jo.toString(4));
+ }
+
+ System.exit(0);
+
+ }
+
+ /**
+ * Adds the unique endpoints.
+ *
+ * @param ja the ja
+ * @throws JSONException the JSON exception
+ */
+ private static void addUniqueEndpoints(JSONArray ja) throws JSONException {
+ JSONObject joItem = new JSONObject();
+ joItem.put("url", "/aai/{version}/service-design-and-creation/models*");
+ joItem.put("method", "get");
+ joItem.put("logicalName", "GetModel");
+ ja.put(joItem);
+ joItem = new JSONObject();
+ joItem.put("url", "/aai/{version}/service-design-and-creation/models*");
+ joItem.put("method", "put");
+ joItem.put("logicalName", "PutModel");
+ ja.put(joItem);
+ joItem = new JSONObject();
+ joItem.put("url", "/aai/{version}/service-design-and-creation/models*");
+ joItem.put("method", "delete");
+ joItem.put("logicalName", "DeleteModel");
+ ja.put(joItem);
+ joItem = new JSONObject();
+ joItem.put("url", "/aai/{version}/service-design-and-creation/named-queries/*");
+ joItem.put("method", "get");
+ joItem.put("logicalName", "GetNamedQuery");
+ ja.put(joItem);
+ }
+
+ /**
+ * Adds the endpoint to json array.
+ *
+ * @param url the url
+ * @param name the name
+ * @param ja the ja
+ * @param apiVersion the api version
+ * @throws JSONException the JSON exception
+ */
+ private static void addEndpointToJsonArray(String url, String name, JSONArray ja, String apiVersion)
+ throws JSONException {
+
+ JSONObject joGet = new JSONObject();
+ JSONObject joPut = new JSONObject();
+ JSONObject joDel = new JSONObject();
+
+ if (!url.endsWith("relationship")) {
+ joGet.put("url", url);
+ joGet.put("method", "get");
+ joGet.put("logicalName", apiVersion + "Get" + name);
+ ja.put(joGet);
+ }
+
+ if (url.endsWith("}") || url.endsWith("relationship")) {
+ joPut.put("url", url);
+ joPut.put("method", "put");
+ joPut.put("logicalName", apiVersion + "Put" + name);
+ ja.put(joPut);
+
+ joDel.put("url", url);
+ joDel.put("method", "delete");
+ joDel.put("logicalName", apiVersion + "Delete" + name);
+ ja.put(joDel);
+
+ }
+
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/MergeResource.java b/aai-resources/src/main/java/org/openecomp/aai/util/MergeResource.java
new file mode 100644
index 0000000..427f65b
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/util/MergeResource.java
@@ -0,0 +1,205 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Date;
+
+import com.sun.tools.javac.util.List;
+
+//SWGK - 01/08/2016 - Helper function to deal with concurrency control
+public class MergeResource {
+
+ //Merge Assumptions:
+ //fromresource and toresource are the same resource type and same resource object
+ //fromresource is the latest version from the DB
+ //toresource is the version of the same resource with updates
+ //merging of child elements are complete overwrite of fromresource corresponding child element
+ //merging of relationshiplist is complete overwrite of fromresource corresponding releationship element
+ //In case of supplying the only specific child element update, please specify the child element type (need not be in canonical form)
+ //For parent only update (not involving child or relationship element update), then all the child elements and relationship list will be set as null in the merged object
+ //For setting null to primitive type (including String) you have to do it after the merge is called specifically for parent only copy
+
+
+ /**
+ * Merge.
+ *
+ * @param <T> the generic type
+ * @param fromresource the fromresource
+ * @param toresource the toresource
+ * @param bupdateChildren the bupdate children
+ * @param childNamelist the child namelist
+ * @param bupdateRelatedLink the bupdate related link
+ * @return the t
+ */
+ public static <T> T merge(T fromresource, T toresource, boolean bupdateChildren, String childNamelist[], boolean bupdateRelatedLink)
+ {
+ Field[] fields = fromresource.getClass().getDeclaredFields();
+ if (fields != null)
+ {
+ for (Field field : fields)
+ {
+ try
+ {
+ field.setAccessible(true);
+ if ( field.getName().equalsIgnoreCase("resourceVersion") )
+ continue;
+ if ( isValidMergeType(field.getType()) )
+ {
+ Object obj = field.get(toresource);
+ // If the updated resource's any property to be set null then one has to set it separately for the merged object
+ if (obj != null)
+ field.set(fromresource, obj);
+ continue;
+ }
+ else
+ // set the child list or relatedTo link to be null so no updates takes place
+ field.set(fromresource, null);
+ //override situation
+ if (bupdateChildren || bupdateRelatedLink)
+ {
+ if (bupdateRelatedLink && field.getName().equalsIgnoreCase("relationshipList"))
+ {
+ Object obj = field.get(toresource);
+ field.set(fromresource, obj);
+ continue;
+ }
+ if (field.getName().equalsIgnoreCase("relationshipList"))
+ if (!bupdateRelatedLink)
+ continue;
+ // not an efficient as it blindly updates all children - onus is on callee to nullify
+ // specific child(ren) that they don't want to update after the merge call.
+ // can be optimized to send a list of children class names in canonical form
+ // but deferring for next release so that only those children can be merged
+ if (bupdateChildren && (childNamelist != null))
+ {
+ for (String classStringName : childNamelist)
+ {
+ if ( !classStringName.isEmpty() && field.getType().toString().toLowerCase().endsWith(classStringName.toLowerCase()) )
+ {
+ Object obj = field.get(toresource);
+ field.set(fromresource, obj);
+ }
+ }
+ continue;
+ }
+
+ if (bupdateChildren && (childNamelist == null))
+ {
+ Object obj = field.get(toresource);
+ field.set(fromresource, obj);
+
+ }
+ }
+
+ }
+ catch (Exception e)
+ {
+
+ }
+
+
+ }
+ }
+ return fromresource;
+ }
+
+
+ /**
+ * Merge.
+ *
+ * @param <T> the generic type
+ * @param fromresource the fromresource
+ * @param toresource the toresource
+ * @return the t
+ */
+ public static <T> T merge(T fromresource, T toresource)
+ {
+ return merge(fromresource, toresource, false, false);
+ }
+
+ /**
+ * Merge.
+ *
+ * @param <T> the generic type
+ * @param fromresource the fromresource
+ * @param toresource the toresource
+ * @param bupdateChildren the bupdate children
+ * @param bupdateRelatedLink the bupdate related link
+ * @return the t
+ */
+ public static <T> T merge(T fromresource, T toresource, boolean bupdateChildren, boolean bupdateRelatedLink)
+ {
+ return merge(fromresource, toresource, bupdateChildren, null, bupdateRelatedLink);
+ }
+
+ /**
+ * Checks if is valid merge type.
+ *
+ * @param fieldType the field type
+ * @return true, if is valid merge type
+ */
+ public static boolean isValidMergeType(Class<?> fieldType) {
+ if (fieldType.equals(String.class)) {
+ return true;
+ } else if (Date.class.isAssignableFrom(fieldType)) {
+ return true;
+ } else if (Number.class.isAssignableFrom(fieldType)) {
+ return true;
+ } else if (fieldType.equals(Integer.TYPE)) {
+ return true;
+ } else if (fieldType.equals(Long.TYPE)) {
+ return true;
+ } else if (Enum.class.isAssignableFrom(fieldType)) {
+ return true;
+ } else if (Boolean.class.isAssignableFrom(fieldType)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ /**
+ * Gets the child return type.
+ *
+ * @param classname the classname
+ * @param methodname the methodname
+ * @return the class
+ */
+ public static Class<?> GetChildReturnType(String classname, String methodname)
+ {
+ try {
+ Class<?> c = Class.forName(classname);
+ Method[] allMethods = c.getDeclaredMethods();
+ for (Method m : allMethods) {
+ if (!m.getName().equals(methodname)) {
+ return m.getReturnType();
+ }
+ }
+ } catch (ClassNotFoundException x) {
+
+ }
+
+ return null;
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/PojoUtils.java b/aai-resources/src/main/java/org/openecomp/aai/util/PojoUtils.java
new file mode 100644
index 0000000..870ddec
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/util/PojoUtils.java
@@ -0,0 +1,738 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.util;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.Multimap;
+import com.thinkaurelius.titan.core.TitanVertex;
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.dynamic.DynamicType;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.openecomp.aai.domain.model.AAIResource;
+import org.openecomp.aai.exceptions.AAIException;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.Map.Entry;
+
+public class PojoUtils {
+
+ /**
+ * Gets the key value list.
+ *
+ * @param <T> the generic type
+ * @param e the e
+ * @param clazz the clazz
+ * @return the key value list
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ */
+ public <T> List<KeyValueList> getKeyValueList(Entity e, T clazz) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ List<KeyValueList> kvList = e.getKeyValueList();
+ Object value = null;
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String propertyName = "";
+
+ for (Method method : methods) {
+ if (method.getName().startsWith("get")) {
+ propertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ if (!(method.getReturnType().getName().contains("aai")) || method.getReturnType().getName().contains("java.util.List")) {
+ value = method.invoke(clazz);
+ KeyValueList kv = new KeyValueList();
+ kv.setKey(propertyName);
+ if (value != null) {
+ kv.setValue(value.toString());
+ } else {
+ kv.setValue("");
+ }
+ kvList.add(kv);
+ }
+ }
+ }
+ return kvList;
+ }
+
+ /**
+ * Gets the json from object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return the json from object
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public <T> String getJsonFromObject(T clazz) throws JsonGenerationException, JsonMappingException, IOException {
+ return getJsonFromObject(clazz, false, true);
+ }
+
+ /**
+ * Gets the json from object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param wrapRoot the wrap root
+ * @param indent the indent
+ * @return the json from object
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ */
+ public <T> String getJsonFromObject(T clazz, boolean wrapRoot, boolean indent) throws JsonGenerationException, JsonMappingException, IOException {
+ ObjectMapper mapper = new ObjectMapper();
+
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+ mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
+ mapper.configure(SerializationFeature.INDENT_OUTPUT, indent);
+ mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, wrapRoot);
+
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, wrapRoot);
+
+ mapper.registerModule(new JaxbAnnotationModule());
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ mapper.writeValue(baos, clazz);
+
+ return baos.toString();
+ }
+
+ /**
+ * Gets the json from dynamic object.
+ *
+ * @param ent the ent
+ * @param jaxbContext the jaxb context
+ * @param includeRoot the include root
+ * @return the json from dynamic object
+ * @throws JsonGenerationException the json generation exception
+ * @throws JsonMappingException the json mapping exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws JAXBException the JAXB exception
+ */
+ public String getJsonFromDynamicObject(DynamicEntity ent, org.eclipse.persistence.jaxb.JAXBContext jaxbContext, boolean includeRoot) throws JsonGenerationException, JsonMappingException, IOException, JAXBException {
+ org.eclipse.persistence.jaxb.JAXBMarshaller marshaller = jaxbContext.createMarshaller();
+
+ marshaller.setProperty(org.eclipse.persistence.jaxb.JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false);
+ marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE) ;
+ marshaller.setProperty("eclipselink.json.include-root", includeRoot);
+ marshaller.setProperty("eclipselink.media-type", "application/json");
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(ent, writer);
+
+ return writer.toString();
+ }
+
+ /**
+ * Gets the xml from object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @return the xml from object
+ * @throws JAXBException the JAXB exception
+ */
+ public <T> String getXmlFromObject(T clazz) throws JAXBException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ JAXBContext jc = JAXBContext.newInstance(clazz.getClass().getPackage().getName());
+
+ Marshaller marshaller = jc.createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ marshaller.marshal(clazz, baos);
+
+ return baos.toString();
+ }
+
+ /**
+ * Gets the lookup key.
+ *
+ * @param baseKey the base key
+ * @param lookupHash the lookup hash
+ * @param keyProps the key props
+ * @return the lookup key
+ */
+ public String getLookupKey (String baseKey, HashMap<String,Object> lookupHash, Collection<String> keyProps) {
+ int baseKeyLen = baseKey.length();
+ StringBuffer newKey = new StringBuffer();
+ if (baseKeyLen > 0) {
+ newKey.append(baseKey);
+ }
+
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ String keyProp = keyPropI.next();
+ if (baseKeyLen > 0) {
+ newKey.append("&");
+ }
+ newKey.append(keyProp + "=" + lookupHash.get(keyProp));
+ }
+ return newKey.toString();
+ }
+
+ /**
+ * Gets the lookup keys.
+ *
+ * @param lookupHashes the lookup hashes
+ * @param _dbRulesNodeKeyProps the db rules node key props
+ * @return the lookup keys
+ */
+ public String getLookupKeys (LinkedHashMap<String,HashMap<String,Object>> lookupHashes, Multimap<String, String> _dbRulesNodeKeyProps) {
+ Iterator<String> it = lookupHashes.keySet().iterator();
+ String lookupKeys = "";
+ while (it.hasNext()) {
+ String objectType = (String)it.next();
+ HashMap<String,Object> lookupHash = lookupHashes.get(objectType);
+
+ Collection<String> keyProps = _dbRulesNodeKeyProps.get(objectType);
+ Iterator <String> keyPropI = keyProps.iterator();
+ while( keyPropI.hasNext() ){
+ lookupKeys += lookupHash.get(keyPropI.next());
+ }
+ }
+ return lookupKeys;
+ }
+
+ /**
+ * Gets the example object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param singleton the singleton
+ * @return the example object
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ */
+ public <T> void getExampleObject(T clazz, boolean singleton) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, AAIException {
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String dnHypPropertyName = "";
+ String upCamPropertyName = "";
+ Random rand = new Random();
+ int randInt = rand.nextInt(10000000);
+
+ for (Method method : methods) {
+ boolean go = false;
+ if (method.getName().startsWith("get")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(3));
+ go = true;
+ } else if (method.getName().startsWith("is")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(2));
+ upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(2));
+ go = true;
+ }
+ // don't return resource-version on a singleton
+ if (singleton && dnHypPropertyName.equals("resource-version")) {
+ go = false;
+ }
+ if (go) {
+ String retType = method.getReturnType().getName();
+ if (!retType.contains("aai") && !retType.contains("java.util.List")) {
+ // get the setter
+ Method meth = clazz.getClass().getMethod("set" + upCamPropertyName, method.getReturnType());
+
+ if (retType.contains("String")) {
+ String val = "example-" + dnHypPropertyName + "-val-" + randInt;
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("long")) {
+ Integer foo = rand.nextInt(100000);
+ meth.invoke(clazz, foo.longValue());
+ } else if (retType.toLowerCase().contains("int")) {
+ meth.invoke(clazz, rand.nextInt(100000));
+ } else if (retType.toLowerCase().contains("short")) {
+ Integer randShort = rand.nextInt(10000);
+ meth.invoke(clazz, randShort.shortValue());
+ } else if (retType.toLowerCase().contains("boolean")) {
+ meth.invoke(clazz, true);
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Gets the aai object from vertex.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param vert the vert
+ * @param _propertyDataTypeMap the property data type map
+ * @return the aai object from vertex
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ */
+ public <T> void getAaiObjectFromVertex(T clazz, TitanVertex vert, Map<String, String> _propertyDataTypeMap) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, AAIException {
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String dnHypPropertyName = "";
+ String upCamPropertyName = "";
+ for (Method method : methods) {
+ boolean go = false;
+ if (method.getName().startsWith("get")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(3));
+ go = true;
+ } else if (method.getName().startsWith("is")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(2));
+ upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(2));
+ go = true;
+ }
+ if (go) {
+ String retType = method.getReturnType().getName();
+ if (!retType.contains("aai") && !retType.contains("java.util.List")) {
+ // get the setter
+ Method meth = clazz.getClass().getMethod("set" + upCamPropertyName, method.getReturnType());
+
+ if (retType.contains("String")) {
+ String val = (String)vert.<String>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("long")) {
+ String titanType = _propertyDataTypeMap.get(dnHypPropertyName);
+
+ Long val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(dnHypPropertyName).orElse(null);
+ if (intVal != null) {
+ val = intVal.longValue();
+ }
+ } else {
+ val = (Long)vert.<Long>property(dnHypPropertyName).orElse(null);
+ }
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("int")) {
+ Integer val = (Integer)vert.<Integer>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("short")) {
+ Short val = (Short)vert.<Short>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("boolean")) {
+ Boolean val = (Boolean)vert.<Boolean>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the topology object.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param _dbRulesNodeNameProps the db rules node name props
+ * @param _dbRulesNodeKeyProps the db rules node key props
+ * @param vert the vert
+ * @return the topology object
+ * @throws IllegalAccessException the illegal access exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws InvocationTargetException the invocation target exception
+ * @throws NoSuchMethodException the no such method exception
+ * @throws SecurityException the security exception
+ * @throws AAIException the AAI exception
+ */
+ public <T> void getTopologyObject(T clazz, Multimap<String, String> _dbRulesNodeNameProps, Multimap<String, String> _dbRulesNodeKeyProps, TitanVertex vert) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, AAIException {
+ Method[] methods = clazz.getClass().getDeclaredMethods();
+ String dnHypPropertyName = "";
+// Object value = null;
+ List<String> includeProps = new ArrayList<String>();
+
+ if ("false".equals(AAIConfig.get("aai.notification.topology.allAttrs", "false"))) {
+ for (Method method : methods) {
+ if (method.getName().startsWith("is")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(2));
+ String upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(2));
+ String retType = method.getReturnType().getName();
+ if (retType.equals("java.lang.Boolean")) {
+ // get the setter
+ Method setterMeth = clazz.getClass().getMethod("set" + upCamPropertyName, method.getReturnType());
+ setterMeth.invoke(clazz, (Boolean)null);
+ }
+ }
+ }
+ String dnHypClassName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,clazz.getClass().getSimpleName());
+ Collection<String> keepProps = _dbRulesNodeNameProps.get(dnHypClassName);
+ Iterator <String> keepPropI = keepProps.iterator();
+ while( keepPropI.hasNext() ){
+ includeProps.add(keepPropI.next());
+ }
+ Collection<String> keepProps2 = _dbRulesNodeKeyProps.get(dnHypClassName);
+ Iterator <String> keepPropI2 = keepProps2.iterator();
+ while( keepPropI2.hasNext() ){
+ includeProps.add(keepPropI2.next());
+ }
+ }
+
+ for (Method method : methods) {
+ if (method.getName().startsWith("get")) {
+ dnHypPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,method.getName().substring(3));
+ if (includeProps.size() > 0) {
+ if (!includeProps.contains(dnHypPropertyName)) {
+ continue;
+ }
+ }
+ String upCamPropertyName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL,method.getName().substring(3));
+ String retType = method.getReturnType().getName();
+ if (!retType.contains("aai") && !retType.contains("java.util.List")) {
+ // get the setter
+ Method meth = clazz.getClass().getMethod("set" + upCamPropertyName, method.getReturnType());
+
+ if (retType.contains("String")) {
+ String val = (String)vert.<String>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("long")) {
+ Long val = (Long)vert.<Long>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("int")) {
+ Integer val = (Integer)vert.<Integer>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ } else if (retType.toLowerCase().contains("short")) {
+ Short val = (Short)vert.<Short>property(dnHypPropertyName).orElse(null);
+ if (val != null) {
+ meth.invoke(clazz, val);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the dynamic topology object.
+ *
+ * @param aaiRes the aai res
+ * @param meObjectType the me object type
+ * @param _dbRulesNodeNameProps the db rules node name props
+ * @param _dbRulesNodeKeyProps the db rules node key props
+ * @param _propertyDataTypeMap the property data type map
+ * @param vert the vert
+ * @return the dynamic topology object
+ * @throws AAIException the AAI exception
+ */
+ public DynamicEntity getDynamicTopologyObject(AAIResource aaiRes, DynamicType meObjectType, Multimap<String, String> _dbRulesNodeNameProps,
+ Multimap<String, String> _dbRulesNodeKeyProps, Map<String, String> _propertyDataTypeMap, TitanVertex vert) throws AAIException {
+
+ DynamicEntity meObject = meObjectType.newDynamicEntity();
+
+ List<String> includeProps = new ArrayList<String>();
+
+ if ("false".equals(AAIConfig.get("aai.notification.topology.allAttrs", "false"))) {
+ String dnHypClassName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,meObjectType.getJavaClass().getSimpleName());
+ Collection<String> keepProps = _dbRulesNodeNameProps.get(dnHypClassName);
+ Iterator <String> keepPropI = keepProps.iterator();
+ while( keepPropI.hasNext() ){
+ includeProps.add(keepPropI.next());
+ }
+ Collection<String> keepProps2 = _dbRulesNodeKeyProps.get(dnHypClassName);
+ Iterator <String> keepPropI2 = keepProps2.iterator();
+ while( keepPropI2.hasNext() ) {
+ includeProps.add(keepPropI2.next());
+ }
+ }
+
+
+
+ for (String attrName : aaiRes.getStringFields()) {
+ if (includeProps.contains(attrName)) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), vert.<String>property(attrName).orElse(null));
+ }
+ }
+ // the attrName might need to be converted to camel case!!!
+ for (String attrName : aaiRes.getLongFields()) {
+ if (includeProps.contains(attrName)) {
+ String titanType = _propertyDataTypeMap.get(attrName);
+
+ Long val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (intVal != null) {
+ val = intVal.longValue();
+ }
+ } else {
+ val = (Long)vert.<Long>property(attrName).orElse(null);
+ }
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+
+ for (String attrName : aaiRes.getIntFields()) {
+ if (includeProps.contains(attrName)) {
+ Integer val = (Integer)vert.<Integer>property(attrName).orElse(null);
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+
+ for (String attrName : aaiRes.getShortFields()) {
+ if (includeProps.contains(attrName)) {
+ String titanType = _propertyDataTypeMap.get(attrName);
+
+ Short val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (intVal != null) {
+ val = intVal.shortValue();
+ }
+ } else {
+ val = (Short)vert.<Short>property(attrName).orElse(null);
+ }
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+
+ for (String attrName : aaiRes.getBooleanFields()) {
+ if (includeProps.contains(attrName)) {
+ Boolean val = (Boolean)vert.<Boolean>property(attrName).orElse(null);
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ return meObject;
+ }
+
+ /**
+ * Gets the aai dynamic object from vertex.
+ *
+ * @param aaiRes the aai res
+ * @param meObject the me object
+ * @param vert the vert
+ * @param _propertyDataTypeMap the property data type map
+ * @return the aai dynamic object from vertex
+ */
+ public void getAaiDynamicObjectFromVertex(AAIResource aaiRes, DynamicEntity meObject, TitanVertex vert,
+ Map<String, String> _propertyDataTypeMap) {
+ getAaiDynamicObjectFromVertex(aaiRes, meObject, vert, _propertyDataTypeMap, null);
+ }
+
+ /**
+ * Gets the aai dynamic object from vertex.
+ *
+ * @param aaiRes the aai res
+ * @param meObject the me object
+ * @param vert the vert
+ * @param _propertyDataTypeMap the property data type map
+ * @param propertyOverRideHash the property over ride hash
+ * @return the aai dynamic object from vertex
+ */
+ @SuppressWarnings("unchecked")
+ public void getAaiDynamicObjectFromVertex(AAIResource aaiRes, DynamicEntity meObject, TitanVertex vert,
+ Map<String, String> _propertyDataTypeMap, HashMap<String, Object> propertyOverRideHash) {
+
+ for (String attrName : aaiRes.getStringFields()) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), vert.<String>property(dbAliasWorkaround(attrName)).orElse(null));
+ }
+ }
+
+ for (String attrName : aaiRes.getStringListFields()) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), vert.<ArrayList<String>>property(attrName).orElse(null));
+ }
+ }
+
+ // the attrName might need to be converted to camel case!!!
+ for (String attrName : aaiRes.getLongFields()) {
+ String titanType = _propertyDataTypeMap.get(attrName);
+ Long val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Object vertexVal = vert.property(attrName).orElse(null);
+ if (vertexVal != null) {
+ if (vertexVal instanceof Integer) {
+ val = ((Integer)vertexVal).longValue();
+
+ } else {
+ val = (Long)vert.<Long>property(attrName).orElse(null);
+ }
+ }
+ } else {
+ val = (Long)vert.<Long>property(attrName).orElse(null);
+ }
+ if (val != null) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ }
+
+ for (String attrName : aaiRes.getIntFields()) {
+ Integer val = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (val != null) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ }
+
+ for (String attrName : aaiRes.getShortFields()) {
+ String titanType = _propertyDataTypeMap.get(attrName);
+ Short val = null;
+ // we have a case where the type in titan is "Integer" but in the POJO it's Long or long
+ if (titanType.toLowerCase().contains("int")) {
+ Integer intVal = (Integer)vert.<Integer>property(attrName).orElse(null);
+ if (intVal != null) {
+ val = intVal.shortValue();
+ }
+ } else {
+ val = (Short)vert.<Short>property(attrName).orElse(null);
+ }
+ if (val != null) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ }
+
+ for (String attrName : aaiRes.getBooleanFields()) {
+ Boolean val = (Boolean)vert.<Boolean>property(attrName).orElse(null);
+ // This is not ideal, but moxy isn't marshalling these attributes.
+ // TODO: Figure out how to see the default-value from the OXM at startup (or at runtime).
+ String dnHypClassName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN,aaiRes.getSimpleName());
+ if (val == null && AAIConfig.getDefaultBools().containsKey(dnHypClassName)) {
+ if (AAIConfig.getDefaultBools().get(dnHypClassName).contains(attrName)) {
+ val = false;
+ }
+ }
+ if (val != null) {
+ if (propertyOverRideHash == null || (propertyOverRideHash != null && propertyOverRideHash.containsKey(attrName))) {
+ meObject.set((CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,attrName)), val);
+ }
+ }
+ }
+
+ }
+
+ private String dbAliasWorkaround(String propName) {
+ final String modelInvariantIdLocal = "model-invariant-id-local";
+ final String modelVersionIdLocal = "model-version-id-local";
+ final String modelInvariantId = "model-invariant-id";
+ final String modelVersionId = "model-version-id";
+
+ if (propName.equals(modelInvariantId)) {
+ return modelInvariantIdLocal;
+ }
+ if (propName.equals(modelVersionId)) {
+ return modelVersionIdLocal;
+ }
+
+ return propName;
+
+ }
+
+ /**
+ * Gets the dynamic example object.
+ *
+ * @param childObject the child object
+ * @param aaiRes the aai res
+ * @param singleton the singleton
+ * @return the dynamic example object
+ */
+ public void getDynamicExampleObject(DynamicEntity childObject, AAIResource aaiRes, boolean singleton) {
+ // TODO Auto-generated method stub
+
+ Random rand = new Random();
+ Integer randInt = rand.nextInt(100000);
+ long range = 100000000L;
+ long randLong = (long)(rand.nextDouble()*range);
+ Integer randShrt = rand.nextInt(20000);
+ short randShort = randShrt.shortValue();
+
+ for (String dnHypAttrName : aaiRes.getStringFields()) {
+
+ if (singleton && ("resource-version").equals(dnHypAttrName)) {
+ continue;
+ }
+
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, "example-" + dnHypAttrName + "-val-" + randInt);
+
+ }
+
+ for (String dnHypAttrName : aaiRes.getStringListFields()) {
+ ArrayList<String> exampleList = new ArrayList<String>();
+ exampleList.add("example-" + dnHypAttrName + "-val-" + randInt + "-" + 1);
+ exampleList.add("example-" + dnHypAttrName + "-val-" + randInt + "-" + 2);
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, exampleList);
+ }
+
+ // the attrName might need to be converted to camel case!!!
+ for (String dnHypAttrName : aaiRes.getLongFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, randLong);
+ }
+
+ for (String dnHypAttrName : aaiRes.getIntFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, randInt);
+ }
+
+ for (String dnHypAttrName : aaiRes.getShortFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, randShort);
+ }
+
+ for (String dnHypAttrName : aaiRes.getBooleanFields()) {
+ String dnCamAttrName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL,dnHypAttrName);
+ childObject.set(dnCamAttrName, Boolean.TRUE);
+ }
+ }
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java b/aai-resources/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java
new file mode 100644
index 0000000..ea674ed
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java
@@ -0,0 +1,283 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.util;
+
+import java.io.StringWriter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.bind.Marshaller;
+
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.eclipse.persistence.dynamic.DynamicEntity;
+import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.openecomp.aai.dmaap.AAIDmaapEventJMSProducer;
+import org.openecomp.aai.exceptions.AAIException;
+import org.openecomp.aai.introspection.Introspector;
+import org.openecomp.aai.introspection.Loader;
+import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException;
+
+public class StoreNotificationEvent {
+
+ private AAIDmaapEventJMSProducer messageProducer;
+ private String fromAppId = "";
+ private String transId = "";
+
+ /**
+ * Instantiates a new store notification event.
+ */
+ public StoreNotificationEvent() {
+ this.messageProducer = new AAIDmaapEventJMSProducer();
+ Message inMessage = PhaseInterceptorChain.getCurrentMessage().getExchange().getInMessage();
+ Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>) inMessage.get(Message.PROTOCOL_HEADERS));
+ if (headersList != null) {
+ List<String> xt = headersList.get("X-TransactionId");
+ if (xt != null) {
+ for (String transIdValue : xt) {
+ transId = transIdValue;
+ }
+ }
+ List<String> fa = headersList.get("X-FromAppId");
+ if (fa != null) {
+ for (String fromAppIdValue : fa) {
+
+ fromAppId = fromAppIdValue;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Store dynamic event.
+ *
+ * @param notificationJaxbContext
+ * the notification jaxb context
+ * @param notificationVersion
+ * the notification version
+ * @param eventHeader
+ * the event header
+ * @param obj
+ * the obj
+ * @throws AAIException
+ * the AAI exception
+ */
+ public void storeDynamicEvent(DynamicJAXBContext notificationJaxbContext, String notificationVersion, DynamicEntity eventHeader, DynamicEntity obj) throws AAIException {
+
+ if (obj == null) {
+ throw new AAIException("AAI_7350");
+ }
+
+ DynamicEntity notificationEvent = notificationJaxbContext.getDynamicType("inventory.aai.openecomp.org." + notificationVersion + ".NotificationEvent").newDynamicEntity();
+
+ if (eventHeader.get("id") == null) {
+ eventHeader.set("id", genDate2() + "-" + UUID.randomUUID().toString());
+ }
+
+ if (eventHeader.get("timestamp") == null) {
+ eventHeader.set("timestamp", genDate());
+ }
+
+ if (eventHeader.get("entityLink") == null) {
+ eventHeader.set("entityLink", "UNK");
+ }
+
+ if (eventHeader.get("action") == null) {
+ eventHeader.set("action", "UNK");
+ }
+
+ if (eventHeader.get("eventType") == null) {
+ eventHeader.set("eventType", AAIConfig.get("aai.notificationEvent.default.eventType", "UNK"));
+ }
+
+ if (eventHeader.get("domain") == null) {
+ eventHeader.set("domain", AAIConfig.get("aai.notificationEvent.default.domain", "UNK"));
+ }
+
+ if (eventHeader.get("sourceName") == null) {
+ eventHeader.set("sourceName", AAIConfig.get("aai.notificationEvent.default.sourceName", "UNK"));
+ }
+
+ if (eventHeader.get("sequenceNumber") == null) {
+ eventHeader.set("sequenceNumber", AAIConfig.get("aai.notificationEvent.default.sequenceNumber", "UNK"));
+ }
+
+ if (eventHeader.get("severity") == null) {
+ eventHeader.set("severity", AAIConfig.get("aai.notificationEvent.default.severity", "UNK"));
+ }
+
+ if (eventHeader.get("version") == null) {
+ eventHeader.set("version", AAIConfig.get("aai.notificationEvent.default.version", "UNK"));
+ }
+
+ if (notificationEvent.get("cambriaPartition") == null) {
+ notificationEvent.set("cambriaPartition", AAIConstants.UEB_PUB_PARTITION_AAI);
+ }
+
+ notificationEvent.set("eventHeader", eventHeader);
+ notificationEvent.set("entity", obj);
+
+ try {
+ StringWriter result = new StringWriter();
+
+ Marshaller marshaller = notificationJaxbContext.createMarshaller();
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.MEDIA_TYPE, "application/json");
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_INCLUDE_ROOT, false);
+ marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, false);
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
+ marshaller.marshal(notificationEvent, result);
+
+ this.sendToDmaapJmsQueue(result.toString());
+
+ } catch (Exception e) {
+ throw new AAIException("AAI_7350", e);
+ }
+ }
+
+ public void storeEvent(Loader loader, Introspector eventHeader, Introspector obj) throws AAIException {
+ if (obj == null) {
+ throw new AAIException("AAI_7350");
+ }
+
+ try {
+ final Introspector notificationEvent = loader.introspectorFromName("notification-event");
+
+ if (eventHeader.getValue("id") == null) {
+ eventHeader.setValue("id", genDate2() + "-" + UUID.randomUUID().toString());
+ }
+
+ if (eventHeader.getValue("timestamp") == null) {
+ eventHeader.setValue("timestamp", genDate());
+ }
+
+ if (eventHeader.getValue("entity-link") == null) {
+ eventHeader.setValue("entity-link", "UNK");
+ }
+
+ if (eventHeader.getValue("action") == null) {
+ eventHeader.setValue("action", "UNK");
+ }
+
+ if (eventHeader.getValue("event-type") == null) {
+ eventHeader.setValue("event-type", AAIConfig.get("aai.notificationEvent.default.eventType", "UNK"));
+ }
+
+ if (eventHeader.getValue("domain") == null) {
+ eventHeader.setValue("domain", AAIConfig.get("aai.notificationEvent.default.domain", "UNK"));
+ }
+
+ if (eventHeader.getValue("source-name") == null) {
+ eventHeader.setValue("source-name", AAIConfig.get("aai.notificationEvent.default.sourceName", "UNK"));
+ }
+
+ if (eventHeader.getValue("sequence-number") == null) {
+ eventHeader.setValue("sequence-number", AAIConfig.get("aai.notificationEvent.default.sequenceNumber", "UNK"));
+ }
+
+ if (eventHeader.getValue("severity") == null) {
+ eventHeader.setValue("severity", AAIConfig.get("aai.notificationEvent.default.severity", "UNK"));
+ }
+
+ if (eventHeader.getValue("version") == null) {
+ eventHeader.setValue("version", AAIConfig.get("aai.notificationEvent.default.version", "UNK"));
+ }
+
+ if (notificationEvent.getValue("cambria-partition") == null) {
+ notificationEvent.setValue("cambria-partition", AAIConstants.UEB_PUB_PARTITION_AAI);
+ }
+
+ notificationEvent.setValue("event-header", eventHeader.getUnderlyingObject());
+ notificationEvent.setValue("entity", obj.getUnderlyingObject());
+
+ String entityJson = notificationEvent.marshal(false);
+ sendToDmaapJmsQueue(entityJson);
+ } catch (JSONException e) {
+ throw new AAIException("AAI_7350", e);
+ } catch (AAIUnknownObjectException e) {
+ throw new AAIException("AAI_7350", e);
+ }
+ }
+
+ private void sendToDmaapJmsQueue(String entityString) throws JSONException {
+
+ JSONObject entityJsonObject = new JSONObject(entityString);
+
+ JSONObject entityJsonObjectUpdated = new JSONObject();
+ JSONObject finalJson = new JSONObject();
+
+ JSONObject entityHeader = entityJsonObject.getJSONObject("event-header");
+ String cambriaPartition = entityJsonObject.getString("cambria.partition");
+
+ entityJsonObject.remove("event-header");
+ entityJsonObject.remove("cambria.partition");
+
+ entityJsonObjectUpdated.put("event-header", entityHeader);
+ entityJsonObjectUpdated.put("cambria.partition", cambriaPartition);
+
+ Iterator<String> iter = entityJsonObject.keys();
+ JSONObject entity = new JSONObject();
+ if (iter.hasNext()) {
+ entity = entityJsonObject.getJSONObject(iter.next());
+ }
+
+ entityJsonObjectUpdated.put("entity", entity);
+
+ finalJson.put("event-topic", "AAI-EVENT");
+ finalJson.put("transId", transId);
+ finalJson.put("fromAppId", fromAppId);
+ finalJson.put("fullId", "");
+ finalJson.put("aaiEventPayload", entityJsonObjectUpdated);
+
+ messageProducer.sendMessageToDefaultDestination(finalJson);
+ }
+
+ /**
+ * Gen date.
+ *
+ * @return the string
+ */
+ public static String genDate() {
+ Date date = new Date();
+ DateFormat formatter = new SimpleDateFormat("YYYYMMdd-HH:mm:ss:SSS");
+ return formatter.format(date);
+ }
+
+ /**
+ * Gen date 2.
+ *
+ * @return the string
+ */
+ public static String genDate2() {
+ Date date = new Date();
+ DateFormat formatter = new SimpleDateFormat("YYYYMMddHHmmss");
+ return formatter.format(date);
+ }
+
+}
diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java b/aai-resources/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java
new file mode 100644
index 0000000..b5c5cbc
--- /dev/null
+++ b/aai-resources/src/main/java/org/openecomp/aai/util/UniquePropertyCheck.java
@@ -0,0 +1,264 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.openecomp.aai
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.openecomp.aai.util;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.slf4j.MDC;
+
+import org.openecomp.aai.exceptions.AAIException;
+import com.att.eelf.configuration.Configuration;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanTransaction;
+import com.thinkaurelius.titan.core.TitanVertex;
+
+
+
+public class UniquePropertyCheck {
+
+
+ private static final String FROMAPPID = "AAI-UTILS";
+ private static final String TRANSID = UUID.randomUUID().toString();
+ private static final String COMPONENT = "UniquePropertyCheck";
+
+ /**
+ * The main method.
+ *
+ * @param args the arguments
+ */
+ public static void main(String[] args) {
+
+
+ Properties props = System.getProperties();
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, "uniquePropertyCheck-logback.xml");
+ props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
+ EELFLogger logger = EELFManager.getInstance().getLogger(UniquePropertyCheck.class.getSimpleName());
+ MDC.put("logFilenameAppender", UniquePropertyCheck.class.getSimpleName());
+
+ if( args == null || args.length != 1 ){
+ String msg = "usage: UniquePropertyCheck propertyName \n";
+ System.out.println(msg);
+ logAndPrint(logger, msg );
+ System.exit(1);
+ }
+ String propertyName = args[0];
+ TitanTransaction graph = null;
+
+ try {
+ AAIConfig.init();
+ System.out.println(" ---- NOTE --- about to open graph (takes a little while)--------\n");
+ TitanGraph tGraph = TitanFactory.open(AAIConstants.REALTIME_DB_CONFIG);
+
+ if( tGraph == null ) {
+ logAndPrint(logger, " Error: Could not get TitanGraph ");
+ System.exit(1);
+ }
+
+ graph = tGraph.newTransaction();
+ if( graph == null ){
+ logAndPrint(logger, "could not get graph object in UniquePropertyCheck() \n");
+ System.exit(0);
+ }
+ }
+ catch (AAIException e1) {
+ String msg = "Threw Exception: [" + e1.toString() + "]";
+ logAndPrint(logger, msg);
+ System.exit(0);
+ }
+ catch (Exception e2) {
+ String msg = "Threw Exception: [" + e2.toString() + "]";
+ logAndPrint(logger, msg);
+ System.exit(0);
+ }
+
+ runTheCheckForUniqueness( TRANSID, FROMAPPID, graph, propertyName, logger );
+ System.exit(0);
+
+ }// End main()
+
+
+ /**
+ * Run the check for uniqueness.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param graph the graph
+ * @param propertyName the property name
+ * @param logger the logger
+ * @return the boolean
+ */
+ public static Boolean runTheCheckForUniqueness( String transId, String fromAppId, TitanTransaction graph,
+ String propertyName, EELFLogger logger ){
+
+ // Note - property can be found in more than one nodetype
+ // our uniqueness constraints are always across the entire db - so this
+ // tool looks across all nodeTypes that the property is found in.
+ Boolean foundDupesFlag = false;
+
+ HashMap <String,String> valuesAndVidHash = new HashMap <String, String> ();
+ HashMap <String,String> dupeHash = new HashMap <String, String> ();
+
+ int propCount = 0;
+ int dupeCount = 0;
+ Iterable <?> vertItr = graph.query().has(propertyName).vertices();
+ Iterator <?> vertItor = vertItr.iterator();
+ while( vertItor.hasNext() ){
+ propCount++;
+ TitanVertex v = (TitanVertex)vertItor.next();
+ String thisVid = v.id().toString();
+ Object val = (v.<Object>property(propertyName)).orElse(null);
+ if( valuesAndVidHash.containsKey(val) ){
+ // We've seen this one before- track it in our dupe hash
+ dupeCount++;
+ if( dupeHash.containsKey(val) ){
+ // This is not the first one being added to the dupe hash for this value
+ String updatedDupeList = dupeHash.get(val) + "|" + thisVid;
+ dupeHash.put(val.toString(), updatedDupeList);
+ }
+ else {
+ // This is the first time we see this value repeating
+ String firstTwoVids = valuesAndVidHash.get(val) + "|" + thisVid;
+ dupeHash.put(val.toString(), firstTwoVids);
+ }
+ }
+ else {
+ valuesAndVidHash.put(val.toString(), thisVid);
+ }
+ }
+
+
+ String info = "\n Found this property [" + propertyName + "] " + propCount + " times in our db.";
+ logAndPrint(logger, info);
+ info = " Found " + dupeCount + " cases of duplicate values for this property.\n\n";
+ logAndPrint(logger, info);
+
+ try {
+ if( ! dupeHash.isEmpty() ){
+ Iterator <?> dupeItr = dupeHash.entrySet().iterator();
+ while( dupeItr.hasNext() ){
+ Map.Entry pair = (Map.Entry) dupeItr.next();
+ String dupeValue = pair.getKey().toString();;
+ String vidsStr = pair.getValue().toString();
+ String[] vidArr = vidsStr.split("\\|");
+ logAndPrint(logger, "\n\n -------------- Found " + vidArr.length
+ + " nodes with " + propertyName + " of this value: [" + dupeValue + "]. Node details: ");
+
+ for( int i = 0; i < vidArr.length; i++ ){
+ String vidString = vidArr[i];
+ Long idLong = Long.valueOf(vidString);
+ TitanVertex tvx = (TitanVertex)graph.getVertex(idLong);
+ showPropertiesAndEdges( TRANSID, FROMAPPID, tvx, logger );
+ }
+ }
+ }
+ }
+ catch( Exception e2 ){
+ logAndPrint(logger, "Threw Exception: [" + e2.toString() + "]");
+ }
+ finally {
+ if( graph != null ){
+ graph.rollback();
+ }
+ }
+
+ return foundDupesFlag;
+
+ }// end of runTheCheckForUniqueness()
+
+
+ /**
+ * Show properties and edges.
+ *
+ * @param transId the trans id
+ * @param fromAppId the from app id
+ * @param tVert the t vert
+ * @param logger the logger
+ */
+ private static void showPropertiesAndEdges( String transId, String fromAppId, TitanVertex tVert,
+ EELFLogger logger ){
+
+ if( tVert == null ){
+ logAndPrint(logger, "Null node passed to showPropertiesAndEdges.");
+ }
+ else {
+ String nodeType = "";
+ Object ob = tVert.<String>property("aai-node-type").orElse(null);
+ if( ob == null ){
+ nodeType = "null";
+ }
+ else{
+ nodeType = ob.toString();
+ }
+
+ logAndPrint(logger, " AAINodeType/VtxID for this Node = [" + nodeType + "/" + tVert.id() + "]");
+ logAndPrint(logger, " Property Detail: ");
+ Iterator<VertexProperty<Object>> pI = tVert.properties();
+ while( pI.hasNext() ){
+ VertexProperty<Object> tp = pI.next();
+ Object val = tp.value();
+ logAndPrint(logger, "Prop: [" + tp.key() + "], val = [" + val + "] ");
+ }
+
+ Iterator <Edge> eI = tVert.edges(Direction.BOTH);
+ if( ! eI.hasNext() ){
+ logAndPrint(logger, "No edges were found for this vertex. ");
+ }
+ while( eI.hasNext() ){
+ TitanEdge ed = (TitanEdge) eI.next();
+ String lab = ed.label();
+ TitanVertex vtx = (TitanVertex) ed.otherVertex(tVert);
+ if( vtx == null ){
+ logAndPrint(logger, " >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< ");
+ }
+ else {
+ String nType = vtx.<String>property("aai-node-type").orElse(null);
+ String vid = vtx.id().toString();
+ logAndPrint(logger, "Found an edge (" + lab + ") from this vertex to a [" + nType + "] node with VtxId = " + vid);
+ }
+ }
+ }
+ } // End of showPropertiesAndEdges()
+
+
+ /**
+ * Log and print.
+ *
+ * @param logger the logger
+ * @param msg the msg
+ */
+ protected static void logAndPrint(EELFLogger logger, String msg) {
+ System.out.println(msg);
+ logger.info(msg);
+ }
+
+}
+
+