Refactor ErrorLogHelper
[aai/aai-common.git] / aai-els-onap-logging / src / main / java / org / onap / aai / logging / ErrorLogHelper.java
index 1cdee73..97548d9 100644 (file)
@@ -3,6 +3,7 @@
  * org.onap.aai
  * ================================================================================
  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 Deutsche Telekom SA.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,22 +24,25 @@ package org.onap.aai.logging;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.StringWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map.Entry;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 import java.util.Properties;
+import java.util.Map.Entry;
 
 import javax.ws.rs.core.MediaType;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.Marshaller;
 
 import org.apache.commons.lang3.StringUtils;
+import org.onap.aai.domain.errorResponse.ErrorMessage;
+import org.onap.aai.domain.errorResponse.ExceptionType;
+import org.onap.aai.domain.errorResponse.Fault;
+import org.onap.aai.domain.errorResponse.Info;
 import org.onap.aai.exceptions.AAIException;
 import org.onap.aai.util.AAIConstants;
-import org.onap.aai.util.MapperUtil;
 import org.onap.logging.filter.base.Constants;
 import org.onap.logging.filter.base.MDCSetup;
 import org.onap.logging.ref.slf4j.ONAPLogConstants;
@@ -46,6 +50,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.MDC;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+
 /**
  *
  * This classes loads the application error properties file
@@ -56,6 +64,8 @@ import org.slf4j.MDC;
 public class ErrorLogHelper {
     private static final Logger LOGGER = LoggerFactory.getLogger(ErrorLogHelper.class);
     private static final HashMap<String, ErrorObject> ERROR_OBJECTS = new HashMap<String, ErrorObject>();
+    private static final ObjectMapper objectMapper = new ObjectMapper();
+    private static final XmlMapper xmlMapper = new XmlMapper();
 
     static {
         try {
@@ -75,17 +85,17 @@ public class ErrorLogHelper {
      */
     public static void loadProperties() throws IOException, ErrorObjectFormatException {
         final String filePath = AAIConstants.AAI_HOME_ETC_APP_PROPERTIES + "error.properties";
-        final InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("error.properties");
+        final InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("error.properties");
         final Properties properties = new Properties();
 
-        try (final FileInputStream fis = new FileInputStream(filePath)) {
+        try (final FileInputStream fileInputStream = new FileInputStream(filePath)) {
             LOGGER.info("Found the error.properties in the following location: {}",
                     AAIConstants.AAI_HOME_ETC_APP_PROPERTIES);
-            properties.load(fis);
+            properties.load(fileInputStream);
         } catch (Exception ex) {
             LOGGER.info("Unable to find the error.properties from filesystem so using file in jar");
-            if (is != null) {
-                properties.load(is);
+            if (inputStream != null) {
+                properties.load(inputStream);
             } else {
                 LOGGER.error("Expected to find the error.properties in the jar but unable to find it");
             }
@@ -123,7 +133,7 @@ public class ErrorLogHelper {
      * @throws IOException
      * @throws ErrorObjectNotFoundException
      */
-    public static ErrorObject getErrorObject(String code) throws ErrorObjectNotFoundException {
+    public static ErrorObject getErrorObject(String code) {
 
         if (code == null)
             throw new IllegalArgumentException("Key cannot be null");
@@ -145,17 +155,16 @@ public class ErrorLogHelper {
      * If no error object is embedded in the AAIException, one will be created using the error object from the
      * AAIException.
      *
-     * @param are must have a restError value whose numeric value must match what should be returned in the REST API
+     * @param aaiException must have a restError value whose numeric value must match what should be returned in the REST API
      * @param variables optional list of variables to flesh out text in error string
      * @return appropriately formatted JSON response per the REST API spec.
      * @throws IOException
      * @deprecated
      */
-    public static String getRESTAPIErrorResponse(AAIException are, ArrayList<String> variables) {
-        List<MediaType> acceptHeaders = new ArrayList<MediaType>();
-        acceptHeaders.add(MediaType.APPLICATION_JSON_TYPE);
+    public static String getRESTAPIErrorResponse(AAIException aaiException, ArrayList<String> variables) {
+        List<MediaType> acceptHeaders = Collections.singletonList(MediaType.APPLICATION_JSON_TYPE);
 
-        return getRESTAPIErrorResponse(acceptHeaders, are, variables);
+        return getRESTAPIErrorResponse(acceptHeaders, aaiException, variables);
     }
 
     /**
@@ -164,287 +173,146 @@ public class ErrorLogHelper {
      * This allows lower level exception detail to be returned to the client to help troubleshoot the problem.
      * If no error object is embedded in the AAIException, one will be created using the error object from the
      * AAIException.
+     * 
+     * @param aaiException
+     * @param variables
+     * @return
+     */
+    public static Fault getErrorResponse(AAIException aaiException,
+            ArrayList<String> variables) {
+        final ErrorObject restErrorObject = getRestErrorObject(aaiException);
+        final String text = createText(restErrorObject);
+        final int placeholderCount = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
+        variables = checkAndEnrichVariables(aaiException, variables, placeholderCount);
+        
+        if (aaiException.getErrorObject().getCategory().equals("1")) {
+            return createPolicyFault(aaiException, text, variables);
+        } else {
+            return createServiceFault(aaiException, text, variables);
+        }
+    }
+
+    /**
      *
-     * @param acceptHeadersOrig the accept headers orig
-     * @param are must have a restError value whose numeric value must match what should be returned in the REST API
+     * @param acceptHeaders the accept headers orig
+     * @param aaiException must have a restError value whose numeric value must match what should be returned in the REST API
      * @param variables optional list of variables to flesh out text in error string
      * @return appropriately formatted JSON response per the REST API spec.
+     * @deprecated in favor of {@link #getErrorResponse(AAIException, ArrayList)}
      */
-    public static String getRESTAPIErrorResponse(List<MediaType> acceptHeadersOrig, AAIException are,
+    @Deprecated
+    public static String getRESTAPIErrorResponse(List<MediaType> acceptHeaders, AAIException aaiException,
             ArrayList<String> variables) {
 
-        StringBuilder text = new StringBuilder();
-        String response = null;
-
-        List<MediaType> acceptHeaders = new ArrayList<MediaType>();
+        List<MediaType> validAcceptHeaders = new ArrayList<MediaType>();
         // we might have an exception but no accept header, so we'll set default to JSON
         boolean foundValidAcceptHeader = false;
-        for (MediaType mt : acceptHeadersOrig) {
-            if (MediaType.APPLICATION_XML_TYPE.isCompatible(mt) || MediaType.APPLICATION_JSON_TYPE.isCompatible(mt)) {
-                acceptHeaders.add(mt);
+        for (MediaType mediaType : acceptHeaders) {
+            if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType) || MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType)) {
+                validAcceptHeaders.add(mediaType);
                 foundValidAcceptHeader = true;
             }
         }
         if (foundValidAcceptHeader == false) {
             // override the exception, client needs to set an appropriate Accept header
-            are = new AAIException("AAI_4014");
-            acceptHeaders.add(MediaType.APPLICATION_JSON_TYPE);
+            aaiException = new AAIException("AAI_4014");
+            validAcceptHeaders.add(MediaType.APPLICATION_JSON_TYPE);
         }
 
-        final ErrorObject eo = are.getErrorObject();
-
-        int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
-
-        ErrorObject restErrorObject;
+        MediaType mediaType = validAcceptHeaders.stream()
+            .filter(MediaType.APPLICATION_JSON_TYPE::isCompatible)
+            .findAny()
+            .orElse(MediaType.APPLICATION_XML_TYPE);
 
+        Fault fault = getErrorResponse(aaiException, variables);
         try {
-            restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + restErrorCode);
-        } catch (ErrorObjectNotFoundException e) {
-            LOGGER.warn("Failed to find related error object AAI_" + restErrorCode + " for error object "
-                    + eo.getErrorCode() + "; using AAI_" + restErrorCode);
-            restErrorObject = eo;
+            return MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType)
+                ? objectMapper.writeValueAsString(fault)
+                : xmlMapper.writeValueAsString(fault);
+        } catch (JsonProcessingException ex) {
+            LOGGER.error(
+                "We were unable to create a rest exception to return on an API because of a parsing error "
+                                    + ex.getMessage());
         }
+        return null;
+    }
 
+    private static String createText(ErrorObject restErrorObject) {
+        final StringBuilder text = new StringBuilder();
         text.append(restErrorObject.getErrorText());
 
         // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
         // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
         // error, are ordered based on the error string.
-        int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
-        text.append(" (msg=%").append(localDataIndex + 1).append(") (ec=%").append(localDataIndex + 2).append(")");
-
-        if (variables == null) {
-            variables = new ArrayList<String>();
-        }
-
-        if (variables.size() < localDataIndex) {
-            ErrorLogHelper.logError("AAI_4011", "data missing for rest error");
-            while (variables.size() < localDataIndex) {
-                variables.add("null");
-            }
-        }
-
-        // This will put the error code and error text into the right positions
-        if (are.getMessage() == null || are.getMessage().length() == 0) {
-            variables.add(localDataIndex++, eo.getErrorText());
-        } else {
-            variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage());
-        }
-        variables.add(localDataIndex, eo.getErrorCodeString());
-
-        for (MediaType mediaType : acceptHeaders) {
-            if (MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType)) {
-                JAXBContext context = null;
-                try {
-                    if (eo.getCategory().equals("1")) {
-
-                        context = JAXBContext.newInstance(org.onap.aai.domain.restPolicyException.Fault.class);
-                        Marshaller m = context.createMarshaller();
-                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
-                        m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
-
-                        org.onap.aai.domain.restPolicyException.ObjectFactory factory =
-                                new org.onap.aai.domain.restPolicyException.ObjectFactory();
-                        org.onap.aai.domain.restPolicyException.Fault fault = factory.createFault();
-                        org.onap.aai.domain.restPolicyException.Fault.RequestError requestError =
-                                factory.createFaultRequestError();
-                        org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException policyException =
-                                factory.createFaultRequestErrorPolicyException();
-                        org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException.Variables polvariables =
-                                factory.createFaultRequestErrorPolicyExceptionVariables();
-
-                        policyException.setMessageId("POL" + eo.getRESTErrorCode());
-                        policyException.setText(text.toString());
-                        for (int i = 0; i < variables.size(); i++) {
-                            polvariables.getVariable().add(variables.get(i));
-                        }
-                        policyException.setVariables(polvariables);
-                        requestError.setPolicyException(policyException);
-                        fault.setRequestError(requestError);
-
-                        StringWriter sw = new StringWriter();
-                        m.marshal(fault, sw);
-
-                        response = sw.toString();
-
-                    } else {
-
-                        context = JAXBContext.newInstance(org.onap.aai.domain.restServiceException.Fault.class);
-                        Marshaller m = context.createMarshaller();
-                        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
-                        m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
-
-                        org.onap.aai.domain.restServiceException.ObjectFactory factory =
-                                new org.onap.aai.domain.restServiceException.ObjectFactory();
-                        org.onap.aai.domain.restServiceException.Fault fault = factory.createFault();
-                        org.onap.aai.domain.restServiceException.Fault.RequestError requestError =
-                                factory.createFaultRequestError();
-                        org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException serviceException =
-                                factory.createFaultRequestErrorServiceException();
-                        org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException.Variables svcvariables =
-                                factory.createFaultRequestErrorServiceExceptionVariables();
-                        serviceException.setMessageId("SVC" + eo.getRESTErrorCode());
-                        serviceException.setText(text.toString());
-                        for (int i = 0; i < variables.size(); i++) {
-                            svcvariables.getVariable().add(variables.get(i));
-                        }
-                        serviceException.setVariables(svcvariables);
-                        requestError.setServiceException(serviceException);
-                        fault.setRequestError(requestError);
-
-                        StringWriter sw = new StringWriter();
-                        m.marshal(fault, sw);
-
-                        response = sw.toString();
-
-                    }
-                } catch (Exception ex) {
-                    LOGGER.error(
-                            "We were unable to create a rest exception to return on an API because of a parsing error "
-                                    + ex.getMessage());
-                }
-            } else {
-                try {
-                    if (eo.getCategory().equals("1")) {
-                        org.onap.aai.domain.restPolicyException.RESTResponse restresp =
-                                new org.onap.aai.domain.restPolicyException.RESTResponse();
-                        org.onap.aai.domain.restPolicyException.RequestError reqerr =
-                                new org.onap.aai.domain.restPolicyException.RequestError();
-                        org.onap.aai.domain.restPolicyException.PolicyException polexc =
-                                new org.onap.aai.domain.restPolicyException.PolicyException();
-                        polexc.setMessageId("POL" + eo.getRESTErrorCode());
-                        polexc.setText(text.toString());
-                        polexc.setVariables(variables);
-                        reqerr.setPolicyException(polexc);
-                        restresp.setRequestError(reqerr);
-                        response = (MapperUtil.writeAsJSONString((Object) restresp));
-
-                    } else {
-                        org.onap.aai.domain.restServiceException.RESTResponse restresp =
-                                new org.onap.aai.domain.restServiceException.RESTResponse();
-                        org.onap.aai.domain.restServiceException.RequestError reqerr =
-                                new org.onap.aai.domain.restServiceException.RequestError();
-                        org.onap.aai.domain.restServiceException.ServiceException svcexc =
-                                new org.onap.aai.domain.restServiceException.ServiceException();
-                        svcexc.setMessageId("SVC" + eo.getRESTErrorCode());
-                        svcexc.setText(text.toString());
-                        svcexc.setVariables(variables);
-                        reqerr.setServiceException(svcexc);
-                        restresp.setRequestError(reqerr);
-                        response = (MapperUtil.writeAsJSONString((Object) restresp));
-                    }
-                } catch (Exception ex) {
-                    LOGGER.error(
-                            "We were unable to create a rest exception to return on an API because of a parsing error "
-                                    + ex.getMessage());
-                }
-            }
-        }
-
-        return response;
+        int placeholderCount = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
+        text.append(" (msg=%").append(placeholderCount + 1).append(") (ec=%").append(placeholderCount + 2).append(")");
+        return text.toString();
     }
 
     /**
      * Gets the RESTAPI error response with logging.
      *
-     * @param acceptHeadersOrig the accept headers orig
-     * @param are the are
+     * @param acceptHeaders the accept headers orig
+     * @param aaiException the are
      * @param variables the variables
      */
-    public static String getRESTAPIErrorResponseWithLogging(List<MediaType> acceptHeadersOrig, AAIException are,
+    public static String getRESTAPIErrorResponseWithLogging(List<MediaType> acceptHeaders, AAIException aaiException,
             ArrayList<String> variables) {
-        String response = ErrorLogHelper.getRESTAPIErrorResponse(acceptHeadersOrig, are, variables);
-        logException(are);
-        return response;
+        logException(aaiException);
+        return ErrorLogHelper.getRESTAPIErrorResponse(acceptHeaders, aaiException, variables);
     }
 
     /**
      * Gets the RESTAPI info response.
      *
-     * @param acceptHeaders the accept headers
-     * @param areList the are list
+     * @param acceptHeaders this param is ignored
+     * @param aaiExceptionsMap the map of AAIException
      * @return the RESTAPI info response
+     * @deprecated {@link ErrorLogHelper#}
+     * @deprecated in favor of {@link #getRestApiInfoResponse(HashMap)}
      */
-    public static Object getRESTAPIInfoResponse(List<MediaType> acceptHeaders,
-            HashMap<AAIException, ArrayList<String>> areList) {
-
-        Object respObj = null;
-
-        org.onap.aai.domain.restResponseInfo.ObjectFactory factory =
-                new org.onap.aai.domain.restResponseInfo.ObjectFactory();
-        org.onap.aai.domain.restResponseInfo.Info info = factory.createInfo();
-        org.onap.aai.domain.restResponseInfo.Info.ResponseMessages responseMessages =
-                factory.createInfoResponseMessages();
-        Iterator<Entry<AAIException, ArrayList<String>>> it = areList.entrySet().iterator();
-
-        while (it.hasNext()) {
-            Entry<AAIException, ArrayList<String>> pair = (Entry<AAIException, ArrayList<String>>) it.next();
-            AAIException are = pair.getKey();
-            ArrayList<String> variables = pair.getValue();
-
-            StringBuilder text = new StringBuilder();
-
-            ErrorObject eo = are.getErrorObject();
-
-            int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
-            ErrorObject restErrorObject;
-            try {
-                restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + String.format("%04d", restErrorCode));
-            } catch (ErrorObjectNotFoundException e) {
-                restErrorObject = eo;
-            }
-            text.append(restErrorObject.getErrorText());
+    @Deprecated
+    public static Object getRESTAPIInfoResponse(ArrayList<MediaType> acceptHeaders,
+            Map<AAIException, ArrayList<String>> aaiExceptionsMap) {
+        return (Object) getRestApiInfoResponse(aaiExceptionsMap);
+    }
 
-            // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
-            // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
-            // error, are ordered based on the error string.
-            int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
-            text.append(" (msg=%").append(localDataIndex + 1).append(") (rc=%").append(localDataIndex + 2).append(")");
+    /**
+     * Gets the RESTAPI info response.
+     *
+     * @param acceptHeaders the accept headers
+     * @param aaiExceptionsMap the are list
+     * @return the RESTAPI info response
+     */
+    public static Info getRestApiInfoResponse(
+            Map<AAIException, ArrayList<String>> aaiExceptionsMap) {
+        List<ErrorMessage> errorMessages = aaiExceptionsMap.entrySet().stream()
+                .map(entry -> createResponseMessage(entry))
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        return new Info(errorMessages);
+    }
 
-            if (variables == null) {
-                variables = new ArrayList<String>();
-            }
+    private static ErrorMessage createResponseMessage(Entry<AAIException, ArrayList<String>> entry) {
+        AAIException aaiException = entry.getKey();
+        ArrayList<String> variables = entry.getValue();
 
-            if (variables.size() < localDataIndex) {
-                ErrorLogHelper.logError("AAI_4011", "data missing for rest error");
-                while (variables.size() < localDataIndex) {
-                    variables.add("null");
-                }
-            }
+        ErrorObject restErrorObject = getRestErrorObject(aaiException);
+        final String text = createText(restErrorObject);
+        final int placeholderCount = StringUtils.countMatches(aaiException.getErrorObject().getErrorText(), "%");
+        variables = checkAndEnrichVariables(aaiException, variables, placeholderCount);
 
-            // This will put the error code and error text into the right positions
-            if (are.getMessage() == null) {
-                variables.add(localDataIndex++, eo.getErrorText());
-            } else {
-                variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage());
-            }
-            variables.add(localDataIndex, eo.getErrorCodeString());
-
-            try {
-                org.onap.aai.domain.restResponseInfo.Info.ResponseMessages.ResponseMessage responseMessage =
-                        factory.createInfoResponseMessagesResponseMessage();
-                org.onap.aai.domain.restResponseInfo.Info.ResponseMessages.ResponseMessage.Variables infovariables =
-                        factory.createInfoResponseMessagesResponseMessageVariables();
-
-                responseMessage.setMessageId("INF" + eo.getRESTErrorCode());
-                responseMessage.setText(text.toString());
-                for (int i = 0; i < variables.size(); i++) {
-                    infovariables.getVariable().add(variables.get(i));
-                }
-
-                responseMessage.setVariables(infovariables);
-                responseMessages.getResponseMessage().add(responseMessage);
-
-            } catch (Exception ex) {
-                LOGGER.error("We were unable to create a rest exception to return on an API because of a parsing error "
-                        + ex.getMessage());
-            }
+        try {
+            return ErrorMessage.builder()
+                .messageId("INF" + aaiException.getErrorObject().getRESTErrorCode())
+                .text(text)
+                .variables(variables)
+                .build();
+        } catch (Exception ex) {
+            LOGGER.error("We were unable to create a rest exception to return on an API because of a parsing error "
+                    + ex.getMessage());
+            return null;
         }
-
-        info.setResponseMessages(responseMessages);
-        respObj = (Object) info;
-
-        return respObj;
     }
 
     /**
@@ -454,125 +322,16 @@ public class ErrorLogHelper {
      * If no error object is embedded in the AAIException, one will be created using the error object from the
      * AAIException.
      *
-     * @param are must have a restError value whose numeric value must match what should be returned in the REST API
+     * @param aaiException must have a restError value whose numeric value must match what should be returned in the REST API
      * @param variables optional list of variables to flesh out text in error string
      * @return appropriately formatted JSON response per the REST API spec.
      */
-    public static String getRESTAPIPolicyErrorResponseXML(AAIException are, ArrayList<String> variables) {
-
-        StringBuilder text = new StringBuilder();
-        String response = null;
-        JAXBContext context = null;
-
-        ErrorObject eo = are.getErrorObject();
-
-        int restErrorCode = Integer.parseInt(eo.getRESTErrorCode());
-        ErrorObject restErrorObject;
-        try {
-            restErrorObject = ErrorLogHelper.getErrorObject("AAI_" + restErrorCode);
-        } catch (ErrorObjectNotFoundException e) {
-            restErrorObject = eo;
-        }
-
-        text.append(restErrorObject.getErrorText());
-
-        // We want to always append the (msg=%n) (ec=%n+1) to the text, but have to find value of n
-        // This assumes that the variables in the ArrayList, which might be more than are needed to flesh out the
-        // error, are ordered based on the error string.
-        int localDataIndex = StringUtils.countMatches(restErrorObject.getErrorText(), "%");
-        text.append(" (msg=%").append(localDataIndex + 1).append(") (ec=%").append(localDataIndex + 2).append(")");
-
-        if (variables == null) {
-            variables = new ArrayList<String>();
-        }
-
-        if (variables.size() < localDataIndex) {
-            ErrorLogHelper.logError("AAI_4011", "data missing for rest error");
-            while (variables.size() < localDataIndex) {
-                variables.add("null");
-            }
-        }
-
-        // This will put the error code and error text into the right positions
-        if (are.getMessage() == null) {
-            variables.add(localDataIndex++, eo.getErrorText());
-        } else {
-            variables.add(localDataIndex++, eo.getErrorText() + ":" + are.getMessage());
-        }
-        variables.add(localDataIndex, eo.getErrorCodeString());
-
-        try {
-            if (eo.getCategory().equals("1")) {
-
-                context = JAXBContext.newInstance(org.onap.aai.domain.restPolicyException.Fault.class);
-                Marshaller m = context.createMarshaller();
-                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
-                m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
-
-                org.onap.aai.domain.restPolicyException.ObjectFactory factory =
-                        new org.onap.aai.domain.restPolicyException.ObjectFactory();
-                org.onap.aai.domain.restPolicyException.Fault fault = factory.createFault();
-                org.onap.aai.domain.restPolicyException.Fault.RequestError requestError =
-                        factory.createFaultRequestError();
-                org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException policyException =
-                        factory.createFaultRequestErrorPolicyException();
-                org.onap.aai.domain.restPolicyException.Fault.RequestError.PolicyException.Variables polvariables =
-                        factory.createFaultRequestErrorPolicyExceptionVariables();
-
-                policyException.setMessageId("POL" + eo.getRESTErrorCode());
-                policyException.setText(text.toString());
-                for (int i = 0; i < variables.size(); i++) {
-                    polvariables.getVariable().add(variables.get(i));
-                }
-                policyException.setVariables(polvariables);
-                requestError.setPolicyException(policyException);
-                fault.setRequestError(requestError);
-
-                StringWriter sw = new StringWriter();
-                m.marshal(fault, sw);
-
-                response = sw.toString();
-
-            } else {
-
-                context = JAXBContext.newInstance(org.onap.aai.domain.restServiceException.Fault.class);
-                Marshaller m = context.createMarshaller();
-                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
-                m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
-
-                org.onap.aai.domain.restServiceException.ObjectFactory factory =
-                        new org.onap.aai.domain.restServiceException.ObjectFactory();
-                org.onap.aai.domain.restServiceException.Fault fault = factory.createFault();
-                org.onap.aai.domain.restServiceException.Fault.RequestError requestError =
-                        factory.createFaultRequestError();
-                org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException serviceException =
-                        factory.createFaultRequestErrorServiceException();
-                org.onap.aai.domain.restServiceException.Fault.RequestError.ServiceException.Variables svcvariables =
-                        factory.createFaultRequestErrorServiceExceptionVariables();
-                serviceException.setMessageId("POL" + eo.getRESTErrorCode());
-                serviceException.setText(text.toString());
-                for (int i = 0; i < variables.size(); i++) {
-                    svcvariables.getVariable().add(variables.get(i));
-                }
-                serviceException.setVariables(svcvariables);
-                requestError.setServiceException(serviceException);
-                fault.setRequestError(requestError);
-
-                StringWriter sw = new StringWriter();
-                m.marshal(fault, sw);
-
-                response = sw.toString();
-
-            }
-        } catch (Exception ex) {
-            LOGGER.error("We were unable to create a rest exception to return on an API because of a parsing error "
-                    + ex.getMessage());
-        }
-        return response;
+    public static String getRESTAPIPolicyErrorResponseXML(AAIException aaiException, ArrayList<String> variables) {
+        return getRESTAPIErrorResponse(Collections.singletonList(MediaType.APPLICATION_XML_TYPE), aaiException, variables);
     }
 
-    public static void logException(AAIException e) {
-        final ErrorObject errorObject = e.getErrorObject();
+    public static void logException(AAIException aaiException) {
+        final ErrorObject errorObject = aaiException.getErrorObject();
         /*
          * String severityCode = errorObject.getSeverityCode(errorObject.getSeverity());
          * 
@@ -586,13 +345,13 @@ public class ErrorLogHelper {
          */
         String stackTrace = "";
         try {
-            stackTrace = LogFormatTools.getStackTop(e);
+            stackTrace = LogFormatTools.getStackTop(aaiException);
         } catch (Exception a) {
             // ignore
         }
         final String errorMessage = new StringBuilder().append(errorObject.getErrorText()).append(":")
                 .append(errorObject.getRESTErrorCode()).append(":").append(errorObject.getHTTPResponseCode())
-                .append(":").append(e.getMessage()).toString().replaceAll("\\n", "^");
+                .append(":").append(aaiException.getMessage()).toString().replaceAll("\\n", "^");
 
         MDCSetup mdcSetup = new MDCSetup();
         mdcSetup.setResponseStatusCode(errorObject.getHTTPResponseCode().getStatusCode());
@@ -622,4 +381,50 @@ public class ErrorLogHelper {
     public static void logError(String code, String message) {
         logException(new AAIException(code, message));
     }
+
+    private static ErrorObject getRestErrorObject(AAIException aaiException) {
+        final int restErrorCode = Integer.parseInt(aaiException.getErrorObject().getRESTErrorCode());
+        return ErrorLogHelper.getErrorObject("AAI_" + restErrorCode);
+    }
+
+    public static Fault createPolicyFault(AAIException aaiException, String text, List<String> variables) {
+        return createFault(aaiException, text, variables, ExceptionType.POLICY);
+    }
+    public static Fault createServiceFault(AAIException aaiException, String text, List<String> variables) {
+        return createFault(aaiException, text, variables, ExceptionType.SERVICE);
+    }
+    private static Fault createFault(AAIException aaiException, String text, List<String> variables, ExceptionType exceptionType) {
+        String typePrefix = ExceptionType.POLICY.equals(exceptionType) ? "POL" : "SVC";
+        Map<ExceptionType, ErrorMessage> requestError = Collections.singletonMap(exceptionType, 
+            ErrorMessage.builder()
+                .messageId(typePrefix+ aaiException.getErrorObject().getRESTErrorCode())
+                .text(text)
+                .variables(variables)
+                .build());
+        return new Fault(requestError);
+    }
+
+    private static ArrayList<String> checkAndEnrichVariables(AAIException aaiException, ArrayList<String> variables, int placeholderCount) {
+        final ErrorObject errorObject = aaiException.getErrorObject();
+        if (variables == null) {
+            variables = new ArrayList<String>();
+        }
+
+        // int placeholderCount = StringUtils.countMatches(errorObject.getErrorText(), "%");
+        if (variables.size() < placeholderCount) {
+            ErrorLogHelper.logError("AAI_4011", "data missing for rest error");
+            while (variables.size() < placeholderCount) {
+                variables.add("null");
+            }
+        }
+
+        // This will put the error code and error text into the right positions
+        if (aaiException.getMessage() == null || aaiException.getMessage().length() == 0) {
+            variables.add(placeholderCount++, errorObject.getErrorText());
+        } else {
+            variables.add(placeholderCount++, errorObject.getErrorText() + ":" + aaiException.getMessage());
+        }
+        variables.add(placeholderCount, errorObject.getErrorCodeString());
+        return variables;
+    }
 }