/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *******************************************************************************/
package org.ofbiz.shipment.thirdparty.dhl;

import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import javolution.util.FastList;
import javolution.util.FastMap;

import org.ofbiz.base.util.Base64;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.HttpClient;
import org.ofbiz.base.util.HttpClientException;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.content.content.ContentWorker;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;
import org.ofbiz.shipment.shipment.ShipmentServices;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

/**
 * DHL ShipmentServices
 *
 * <p>Implementation of DHL US domestic shipment interface using DHL ShipIT XML APi.</p>
 *
 * Shipment services not supported in DHL ShipIT 1.1
 * <ul>
 * <li>Multiple Piece shipping (Shipment must not have more than one
 * ShipmentPackage)</li>
 * <li>Dynamic editing of previously submitted shipment (void first then
 * resubmit instead)</li>
 * <li>Label size 4"x6"</li>
 * <li>Out of origin shipping</li>
 * </ul>
 *
 * TODO: International
 */
public class DhlServices {

    public final static String module = DhlServices.class.getName();
    public final static String shipmentPropertiesFile = "shipment.properties";
    public final static String DHL_WEIGHT_UOM_ID = "WT_lb"; // weight Uom used by DHL
    public static final String resourceError = "ProductUiLabels";

    /**
     * Opens a URL to DHL and makes a request.
     *
     * @param xmlString Name of the DHL service to invoke
     * @param delegator the delegator
     * @param shipmentGatewayConfigId the shipment gateway config id
     * @param resource the resource file (i.e. shipment.properties)
     * @param locale locale in use
     * @return XML string response from DHL
     * @throws DhlConnectException
     */
    public static String sendDhlRequest(String xmlString, Delegator delegator, String shipmentGatewayConfigId, 
            String resource, Locale locale) throws DhlConnectException {
        String conStr = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "connectUrl", resource, "shipment.dhl.connect.url");
        if (conStr == null) {
            throw new DhlConnectException(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlConnectUrlIncomplete", locale));
        }

        // xmlString should contain the auth document at the beginning
        // all documents require an <?xml version="1.0"?> header
        if (xmlString == null) {
            throw new DhlConnectException(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlXmlCannotBeNull", locale));
        }

        // prepare the connect string
        conStr = conStr.trim();

        String timeOutStr = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "connectTimeout", 
                resource, "shipment.dhl.connect.timeout", "60");
        int timeout = 60;
        try {
            timeout = Integer.parseInt(timeOutStr);
        } catch (NumberFormatException e) {
            Debug.logError(e, "Unable to set timeout to " + timeOutStr + " using default " + timeout);
        }

        if (Debug.verboseOn()) {
            Debug.logVerbose("DHL Connect URL : " + conStr, module);
            Debug.logVerbose("DHL XML String : " + xmlString, module);
        }

        HttpClient http = new HttpClient(conStr);
        http.setTimeout(timeout * 1000);
        String response = null;
        try {
            response = http.post(xmlString);
        } catch (HttpClientException e) {
            Debug.logError(e, "Problem connecting with DHL server", module);
            throw new DhlConnectException(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlConnectUrlProblem", UtilMisc.toMap("errorString", e), locale), e);
        }

        if (response == null) {
            throw new DhlConnectException(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlReceivedNullResponse", locale));
        }
        if (Debug.verboseOn()) {
            Debug.logVerbose("DHL Response : " + response, module);
        }

        return response;
    }


    /*
     * Service to obtain a rate estimate from DHL for a shipment. Notes: Only one package per shipment currently supported by DHL ShipIT.
     * If this service returns a null shippingEstimateAmount, then the shipment has not been processed
     */
    public static Map<String, Object> dhlRateEstimate(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");

        // some of these can be refactored
        String carrierPartyId = (String) context.get("carrierPartyId");
        String shipmentMethodTypeId = (String) context.get("shipmentMethodTypeId");
        String shippingContactMechId = (String) context.get("shippingContactMechId");
        BigDecimal shippableWeight = (BigDecimal) context.get("shippableWeight");

        if (shipmentMethodTypeId.equals("NO_SHIPPING")) {
            Map<String, Object> result = ServiceUtil.returnSuccess();
            result.put("shippingEstimateAmount", null);
            return result;
        }

        // translate shipmentMethodTypeId to DHL service code
        String dhlShipmentDetailCode = null;
        try {
            GenericValue carrierShipmentMethod = delegator.findOne("CarrierShipmentMethod", UtilMisc.toMap("shipmentMethodTypeId", shipmentMethodTypeId,
                    "partyId", carrierPartyId, "roleTypeId", "CARRIER"), false);
            if (carrierShipmentMethod == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentDhlNoCarrierShipmentMethod",
                        UtilMisc.toMap("carrierPartyId", carrierPartyId, "shipmentMethodTypeId", shipmentMethodTypeId), locale));
            }
            dhlShipmentDetailCode = carrierShipmentMethod.getString("carrierServiceCode");
        } catch (GenericEntityException e) {
            Debug.logError(e, "Failed to get rate estimate: " + e.getMessage(), module);
        }

        String resource = (String) context.get("serviceConfigProps");
        String shipmentGatewayConfigId = (String) context.get("shipmentGatewayConfigId");
        
        // shipping credentials (configured in properties)
        String userid = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessUserId", resource, "shipment.dhl.access.userid");
        String password = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessPassword", resource, "shipment.dhl.access.password");
        String shippingKey = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessShippingKey", resource, "shipment.dhl.access.shippingKey");
        String accountNbr = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessAccountNbr", resource, "shipment.dhl.access.accountNbr");
        if ((shippingKey == null) || (accountNbr == null) || (shippingKey.length() == 0) || (accountNbr.length() == 0)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlGatewayNotAvailable", locale));
        }

        // obtain the ship-to address
        GenericValue shipToAddress = null;
        if (shippingContactMechId != null) {
            try {
                shipToAddress = delegator.findOne("PostalAddress", UtilMisc.toMap("contactMechId", shippingContactMechId), false);
                if (shipToAddress == null) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                            "FacilityShipmentUnableFoundShipToAddresss", locale));
                }
            }
            catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
        }

        if ((shippableWeight == null) || (shippableWeight.compareTo(BigDecimal.ZERO) <= 0)) {
            String tmpValue = UtilProperties.getPropertyValue(shipmentPropertiesFile, "shipment.default.weight.value");
            if (tmpValue != null) {
                try {
                    shippableWeight = new BigDecimal(tmpValue);
                } catch (Exception e) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                            "FacilityShipmentDhlDefaultShippableWeightNotConfigured", locale));
                }
            }
        }

        // TODO: if a weight UOM is passed in, use convertUom service to convert it here
        if (shippableWeight.compareTo(BigDecimal.ONE) < 0) {
            Debug.logWarning("DHL Estimate: Weight is less than 1 lb, submitting DHL minimum of 1 lb for estimate.", module);
            shippableWeight = BigDecimal.ONE;
        }
        if ((dhlShipmentDetailCode.equals("G") && shippableWeight.compareTo(new BigDecimal("999")) > 0) || (shippableWeight.compareTo(new BigDecimal("150")) > 0)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlShippableWeightExceed", locale));
        }
        String weight = (Integer.valueOf((int) shippableWeight.longValue())).toString();

        // create AccessRequest XML doc using FreeMarker template
        String templateName = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "rateEstimateTemplate", resource, "shipment.dhl.template.rate.estimate");
        if ((templateName == null) || (templateName.trim().length() == 0)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlShipmentTemplateLocationNotFound", locale));
        }
        StringWriter outWriter = new StringWriter();
        Map<String, Object> inContext = FastMap.newInstance();
        inContext.put("action", "RateEstimate");
        inContext.put("userid", userid);
        inContext.put("password", password);
        inContext.put("accountNbr", accountNbr);
        inContext.put("shippingKey", shippingKey);
        inContext.put("shipDate", UtilDateTime.nowTimestamp());
        inContext.put("dhlShipmentDetailCode", dhlShipmentDetailCode);
        inContext.put("weight", weight);
        inContext.put("state", shipToAddress.getString("stateProvinceGeoId"));
        // DHL ShipIT API does not accept ZIP+4
        if ((shipToAddress.getString("postalCode") != null) && (shipToAddress.getString("postalCode").length() > 5)) {
            inContext.put("postalCode", shipToAddress.getString("postalCode").substring(0,5));
        } else {
            inContext.put("postalCode", shipToAddress.getString("postalCode"));
        }
        try {
            ContentWorker.renderContentAsText(dispatcher, delegator, templateName, outWriter, inContext, locale, "text/plain", null, null, false);
        } catch (Exception e) {
            Debug.logError(e, "Cannot get DHL Estimate: Failed to render DHL XML Request.", module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlShipmentTemplateError", locale));
        }
        String requestString = outWriter.toString();
        if (Debug.verboseOn()) {
            Debug.logVerbose(requestString, module);
        }

        // send the request
        String rateResponseString = null;
        try {
            rateResponseString = sendDhlRequest(requestString, delegator, shipmentGatewayConfigId, resource, locale);
            if (Debug.verboseOn()) {
                Debug.logVerbose(rateResponseString, module);
            }
        }
        catch (DhlConnectException e) {
            String uceErrMsg = "Error sending DHL request for DHL Service Rate: " + e.toString();
            Debug.logError(e, uceErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlShipmentTemplateSendingError", 
                    UtilMisc.toMap("errorString", e.toString()), locale));
        }

        Document rateResponseDocument = null;
        try {
            rateResponseDocument = UtilXml.readXmlDocument(rateResponseString, false);
            return handleDhlRateResponse(rateResponseDocument, locale);
        }
        catch (SAXException e2) {
            String excErrMsg = "Error parsing the RatingServiceResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentFedexShipmentTemplateParsingError", 
                    UtilMisc.toMap("errorString", e2.toString()), locale));
        }
        catch (ParserConfigurationException e2) {
            String excErrMsg = "Error parsing the RatingServiceResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentFedexShipmentTemplateParsingError", 
                    UtilMisc.toMap("errorString", e2.toString()), locale));
        }
        catch (IOException e2) {
            String excErrMsg = "Error parsing the RatingServiceResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentFedexShipmentTemplateParsingError", 
                    UtilMisc.toMap("errorString", e2.toString()), locale));
        }
    }

    /*
     * Parses an XML document from DHL to get the rate estimate
     */
    public static Map<String, Object> handleDhlRateResponse(Document rateResponseDocument, Locale locale) {
        List<Object> errorList = FastList.newInstance();
        Map<String, Object> dhlRateCodeMap = FastMap.newInstance();
        // process RateResponse
        Element rateResponseElement = rateResponseDocument.getDocumentElement();
        DhlServices.handleErrors(rateResponseElement, errorList, locale);
        if (UtilValidate.isNotEmpty(errorList)) {
            return ServiceUtil.returnError(errorList);
        }
        // handle Response element info
        Element responseElement = UtilXml.firstChildElement(rateResponseElement, "Shipment");
        //Element responseResultElement = UtilXml.firstChildElement(responseElement, "Result");
        Element responseEstimateDetailElement = UtilXml.firstChildElement(responseElement, "EstimateDetail");

        DhlServices.handleErrors(responseElement, errorList, locale);
        if (UtilValidate.isNotEmpty(errorList)) {
            return ServiceUtil.returnError(errorList);
        }
        
        /*
        String responseStatusCode = UtilXml.childElementValue(responseResultElement, "Code");
        String responseStatusDescription = UtilXml.childElementValue(responseResultElement, "Desc");
        */

        String dateGenerated = UtilXml.childElementValue(
                responseEstimateDetailElement, "DateGenerated");

        Element responseServiceLevelCommitmentElement = UtilXml
            .firstChildElement(responseEstimateDetailElement,
                    "ServiceLevelCommitment");
        String responseServiceLevelCommitmentDescription = UtilXml
            .childElementValue(responseServiceLevelCommitmentElement,
                    "Desc");

        Element responseRateEstimateElement = UtilXml.firstChildElement(
                responseEstimateDetailElement, "RateEstimate");
        String responseTotalChargeEstimate = UtilXml.childElementValue(
                responseRateEstimateElement, "TotalChargeEstimate");
        Element responseChargesElement = UtilXml.firstChildElement(
                responseRateEstimateElement, "Charges");
        List<? extends Element> chargeNodeList = UtilXml.childElementList(responseChargesElement,
                "Charge");

        List<Map<String, String>> chargeList = FastList.newInstance();
        if (UtilValidate.isNotEmpty(chargeNodeList)) {
            for (Element responseChargeElement: chargeNodeList) {
                Map<String, String> charge = FastMap.newInstance();

                Element responseChargeTypeElement = UtilXml.firstChildElement(
                        responseChargeElement, "Type");

                String responseChargeTypeCode = UtilXml.childElementValue(
                        responseChargeTypeElement, "Code");
                String responseChargeTypeDesc = UtilXml.childElementValue(
                        responseChargeTypeElement, "Desc");
                String responseChargeValue = UtilXml.childElementValue(
                        responseChargeElement, "Value");

                charge.put("chargeTypeCode", responseChargeTypeCode);
                charge.put("chargeTypeDesc", responseChargeTypeDesc);
                charge.put("chargeValue", responseChargeValue);
                chargeList.add(charge);
            }
        }
        BigDecimal shippingEstimateAmount = new BigDecimal(responseTotalChargeEstimate);
        dhlRateCodeMap.put("dateGenerated", dateGenerated);
        dhlRateCodeMap.put("serviceLevelCommitment",
                responseServiceLevelCommitmentDescription);
        dhlRateCodeMap.put("totalChargeEstimate", responseTotalChargeEstimate);
        dhlRateCodeMap.put("chargeList", chargeList);

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("shippingEstimateAmount", shippingEstimateAmount);
        result.put("dhlRateCodeMap", dhlRateCodeMap);
        return result;
    }

    /*
     * Register a DHL account for shipping by obtaining the DHL shipping key
     */
    public static Map<String, Object> dhlRegisterInquire(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        String resource = (String) context.get("serviceConfigProps");
        String shipmentGatewayConfigId = (String) context.get("shipmentGatewayConfigId");
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = FastMap.newInstance();
        String postalCode = (String) context.get("postalCode");
        String accountNbr = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessAccountNbr",
                resource, "shipment.dhl.access.accountNbr");
        if (accountNbr == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlAccessAccountNbrMandotoryForRegisterAccount", locale));
        }
        // create AccessRequest XML doc
        Document requestDocument = createAccessRequestDocument(delegator, shipmentGatewayConfigId, resource);
        String requestString = null;
        Element requesElement = requestDocument.getDocumentElement();

        Element registerRequestElement = UtilXml.addChildElement(requesElement, "Register", requestDocument);
        registerRequestElement.setAttribute("version", "1.0");
        registerRequestElement.setAttribute("action", "ShippingKey");
        UtilXml.addChildElementValue(registerRequestElement, "AccountNbr", accountNbr, requestDocument);
        UtilXml.addChildElementValue(registerRequestElement, "PostalCode", postalCode, requestDocument);

        try {
            requestString = UtilXml.writeXmlDocument(requestDocument);
            Debug.logInfo("AccessRequest XML Document:" + requestString, module);
        } catch (IOException e) {
            String ioeErrMsg = "Error writing the AccessRequest XML Document to a String: " + e.toString();
            Debug.logError(e, ioeErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlErrorAccessRequestXmlToString", 
                    UtilMisc.toMap("errorString", e.toString()), locale));
        }
        // send the request
        String registerResponseString = null;
        try {
            registerResponseString = sendDhlRequest(requestString, delegator, shipmentGatewayConfigId, resource, locale);
            Debug.logInfo("DHL request for DHL Register Account:" + registerResponseString, module);
        } catch (DhlConnectException e) {
            String uceErrMsg = "Error sending DHL request for DHL Register Account: " + e.toString();
            Debug.logError(e, uceErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlErrorSendingRequestRegisterAccount", 
                    UtilMisc.toMap("errorString", e.toString()), locale));
        }

        Document registerResponseDocument = null;
        try {
            registerResponseDocument = UtilXml.readXmlDocument(registerResponseString, false);
            result = handleDhlRegisterResponse(registerResponseDocument, locale);
            Debug.logInfo("DHL response for DHL Register Account:" + registerResponseString, module);
        } catch (SAXException e2) {
            String excErrMsg = "Error parsing the RegisterAccountServiceSelectionResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlErrorParsingRegisterAccountResponse", 
                    UtilMisc.toMap("errorString", e2.toString()), locale));
        } catch (ParserConfigurationException e2) {
            String excErrMsg = "Error parsing the RegisterAccountServiceSelectionResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlErrorParsingRegisterAccountResponse", 
                    UtilMisc.toMap("errorString", e2.toString()), locale));
        } catch (IOException e2) {
            String excErrMsg = "Error parsing the RegisterAccountServiceSelectionResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlErrorParsingRegisterAccountResponse", 
                    UtilMisc.toMap("errorString", e2.toString()), locale));
        }

        return result;
    }

    /*
     * Parse response from DHL registration request to get shipping key
     */
    public static Map<String, Object> handleDhlRegisterResponse(Document registerResponseDocument, Locale locale) {
        List<Object> errorList = FastList.newInstance();
        // process RegisterResponse
        Element registerResponseElement = registerResponseDocument.getDocumentElement();
        DhlServices.handleErrors(registerResponseElement, errorList, locale);
        if (UtilValidate.isNotEmpty(errorList)) {
            return ServiceUtil.returnError(errorList);
        }
        // handle Response element info
        Element responseElement = UtilXml.firstChildElement(registerResponseElement, "Register");
        //Element responseResultElement = UtilXml.firstChildElement(responseElement, "Result");

        DhlServices.handleErrors(responseElement, errorList, locale);
        if (UtilValidate.isNotEmpty(errorList)) {
            return ServiceUtil.returnError(errorList);
        }
        //String responseStatusCode = UtilXml.childElementValue(responseResultElement, "Code");
        //String responseStatusDescription = UtilXml.childElementValue(responseResultElement, "Desc");

        String responseShippingKey = UtilXml.childElementValue(responseElement,"ShippingKey");
        //String responsePostalCode = UtilXml.childElementValue(responseElement,"PostalCode");

        Map<String, Object> result = ServiceUtil.returnSuccess();
        result.put("shippingKey", responseShippingKey);
        return result;
    }

    /*
     * Pass a shipment request to DHL via ShipIT and get a tracking number and a label back, among other things
     */

    public static Map<String, Object> dhlShipmentConfirm(DispatchContext dctx, Map<String, ? extends Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");

        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String shipmentId = (String) context.get("shipmentId");
        String shipmentRouteSegmentId = (String) context.get("shipmentRouteSegmentId");
        
        Map<String, Object> shipmentGatewayConfig = ShipmentServices.getShipmentGatewayConfigFromShipment(delegator, shipmentId, locale);
        String shipmentGatewayConfigId = (String) shipmentGatewayConfig.get("shipmentGatewayConfigId");
        String resource = (String) shipmentGatewayConfig.get("configProps");
        if (UtilValidate.isEmpty(shipmentGatewayConfigId) && UtilValidate.isEmpty(resource)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlGatewayNotAvailable", locale));
        }
        
        String shipmentConfirmResponseString = null;
        try {
            GenericValue shipment = delegator.findOne("Shipment", UtilMisc.toMap("shipmentId", shipmentId), false);
            if (shipment == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "ProductShipmentNotFoundId", locale) + shipmentId);
            }
            GenericValue shipmentRouteSegment = delegator.findOne("ShipmentRouteSegment", UtilMisc.toMap("shipmentId", shipmentId, "shipmentRouteSegmentId", shipmentRouteSegmentId), false);
            if (shipmentRouteSegment == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "ProductShipmentRouteSegmentNotFound", 
                        UtilMisc.toMap("shipmentId", shipmentId, "shipmentRouteSegmentId", shipmentRouteSegmentId), locale));
            }

            if (!"DHL".equals(shipmentRouteSegment.getString("carrierPartyId"))) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentDhlNotRouteSegmentCarrier", 
                        UtilMisc.toMap("shipmentRouteSegmentId", shipmentRouteSegmentId, "shipmentId", shipmentId), locale));
            }

            // add ShipmentRouteSegment carrierServiceStatusId, check before all DHL services
            if (UtilValidate.isNotEmpty(shipmentRouteSegment.getString("carrierServiceStatusId")) && !"SHRSCS_NOT_STARTED".equals(shipmentRouteSegment.getString("carrierServiceStatusId"))) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentDhlRouteSegmentStatusNotStarted", 
                        UtilMisc.toMap("shipmentRouteSegmentId", shipmentRouteSegmentId, "shipmentId", shipmentId, 
                                "shipmentRouteSegmentStatus", shipmentRouteSegment.getString("carrierServiceStatusId")), locale));
            }

            // Get Origin Info
            GenericValue originPostalAddress = shipmentRouteSegment.getRelatedOne("OriginPostalAddress", false);
            if (originPostalAddress == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentRouteSegmentOriginPostalAddressNotFound", 
                        UtilMisc.toMap("shipmentId", shipmentId, "shipmentRouteSegmentId", shipmentRouteSegmentId), locale));
            }
            GenericValue originTelecomNumber = shipmentRouteSegment.getRelatedOne("OriginTelecomNumber", false);
            if (originTelecomNumber == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentRouteSegmentOriginTelecomNumberNotFound", 
                        UtilMisc.toMap("shipmentId", shipmentId, "shipmentRouteSegmentId", shipmentRouteSegmentId), locale));
            }
            String originPhoneNumber = originTelecomNumber.getString("areaCode") + originTelecomNumber.getString("contactNumber");
            // don't put on country code if not specified or is the US country code (UPS wants it this way and assuming DHL will accept this)
            if (UtilValidate.isNotEmpty(originTelecomNumber.getString("countryCode")) && !"001".equals(originTelecomNumber.getString("countryCode"))) {
                originPhoneNumber = originTelecomNumber.getString("countryCode") + originPhoneNumber;
            }
            originPhoneNumber = StringUtil.replaceString(originPhoneNumber, "-", "");
            originPhoneNumber = StringUtil.replaceString(originPhoneNumber, " ", "");

            // lookup the two letter country code (in the geoCode field)
            GenericValue originCountryGeo = originPostalAddress.getRelatedOne("CountryGeo", false);
            if (originCountryGeo == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentRouteSegmentOriginCountryGeoNotFound", 
                        UtilMisc.toMap("shipmentId", shipmentId, "shipmentRouteSegmentId", shipmentRouteSegmentId), locale));
            }

            // Get Dest Info
            GenericValue destPostalAddress = shipmentRouteSegment.getRelatedOne("DestPostalAddress", false);
            if (destPostalAddress == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentRouteSegmentDestPostalAddressNotFound", 
                        UtilMisc.toMap("shipmentId", shipmentId, "shipmentRouteSegmentId", shipmentRouteSegmentId), locale));
            }

            // DHL requires destination phone number, default to sender # if no customer number
            String destPhoneNumber = originPhoneNumber;
            GenericValue destTelecomNumber = shipmentRouteSegment.getRelatedOne("DestTelecomNumber", false);
            if (destTelecomNumber != null) {
                destPhoneNumber = destTelecomNumber.getString("areaCode") + destTelecomNumber.getString("contactNumber");
                // don't put on country code if not specified or is the US country code (UPS wants it this way)
                if (UtilValidate.isNotEmpty(destTelecomNumber.getString("countryCode")) && !"001".equals(destTelecomNumber.getString("countryCode"))) {
                    destPhoneNumber = destTelecomNumber.getString("countryCode") + destPhoneNumber;
                }
                destPhoneNumber = StringUtil.replaceString(destPhoneNumber, "-", "");
                destPhoneNumber = StringUtil.replaceString(destPhoneNumber, " ", "");
            }

            String recipientEmail = null;
            Map<String, Object> results = dispatcher.runSync("getPartyEmail", UtilMisc.toMap("partyId", shipment.get("partyIdTo"), "userLogin", userLogin));
            if (results.get("emailAddress") != null) {
                recipientEmail = (String) results.get("emailAddress");
            }

            // lookup the two letter country code (in the geoCode field)
            GenericValue destCountryGeo = destPostalAddress.getRelatedOne("CountryGeo", false);
            if (destCountryGeo == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentRouteSegmentDestCountryGeoNotFound", 
                        UtilMisc.toMap("shipmentId", shipmentId, "shipmentRouteSegmentId", shipmentRouteSegmentId), locale));
            }

            List<GenericValue> shipmentPackageRouteSegs = shipmentRouteSegment.getRelated("ShipmentPackageRouteSeg", null, UtilMisc.toList("+shipmentPackageSeqId"), false);
            if (UtilValidate.isEmpty(shipmentPackageRouteSegs)) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentPackageRouteSegsNotFound", 
                        UtilMisc.toMap("shipmentId", shipmentId, "shipmentRouteSegmentId", shipmentRouteSegmentId), locale));
            }
            if (shipmentPackageRouteSegs.size() != 1) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentDhlMultiplePackagesNotSupported", locale));
            }

            // get the weight from the ShipmentRouteSegment first, which overrides all later weight computations
            boolean hasBillingWeight = false;  // for later overrides
            BigDecimal billingWeight = shipmentRouteSegment.getBigDecimal("billingWeight");
            String billingWeightUomId = shipmentRouteSegment.getString("billingWeightUomId");
            if ((billingWeight != null) && (billingWeight.compareTo(BigDecimal.ZERO) > 0)) {
                hasBillingWeight = true;
                if (billingWeightUomId == null) {
                    Debug.logWarning("Shipment Route Segment missing billingWeightUomId in shipmentId " + shipmentId,  module);
                    billingWeightUomId = "WT_lb"; // TODO: this should be specified in a properties file
                }
                // convert
                results = dispatcher.runSync("convertUom", UtilMisc.<String, Object>toMap("uomId", billingWeightUomId, "uomIdTo", DHL_WEIGHT_UOM_ID, "originalValue", billingWeight));
                if (ServiceUtil.isError(results) || (results.get("convertedValue") == null)) {
                    Debug.logWarning("Unable to convert billing weights for shipmentId " + shipmentId , module);
                    // try getting the weight from package instead
                    hasBillingWeight = false;
                } else {
                    billingWeight = (BigDecimal) results.get("convertedValue");
                }
            }

            // loop through Shipment segments (NOTE: only one supported, loop is here for future refactoring reference)
            BigDecimal packageWeight = null;
            for (GenericValue shipmentPackageRouteSeg: shipmentPackageRouteSegs) {
                GenericValue shipmentPackage = shipmentPackageRouteSeg.getRelatedOne("ShipmentPackage", false);
                GenericValue shipmentBoxType = shipmentPackage.getRelatedOne("ShipmentBoxType", false);
                /*
                List<GenericValue> carrierShipmentBoxTypes = shipmentPackage.getRelated("CarrierShipmentBoxType", UtilMisc.toMap("partyId", "DHL"), null, false);
                GenericValue carrierShipmentBoxType = null;
                if (carrierShipmentBoxTypes.size() > 0) {
                    carrierShipmentBoxType = carrierShipmentBoxTypes.get(0);
                }
                */

                // TODO: determine what default UoM is (assuming inches) - there should be a defaultDimensionUomId in Facility
                if (shipmentBoxType != null) {
                    /*
                    GenericValue dimensionUom = shipmentBoxType.getRelatedOne("DimensionUom", false);
                    String length = shipmentBoxType.get("boxLength").toString();
                    String width = shipmentBoxType.get("boxWidth").toString();
                    String height = shipmentBoxType.get("boxHeight").toString();
                     */
                }

                // next step is weight determination, so skip if we have a billing weight
                if (hasBillingWeight) continue;

                // compute total packageWeight (for now, just one package)
                if (shipmentPackage.getString("weight") != null) {
                    packageWeight = new BigDecimal(shipmentPackage.getString("weight"));
                } else {
                    // use default weight if available
                    try {
                        packageWeight = new BigDecimal(UtilProperties.getPropertyValue(shipmentPropertiesFile, "shipment.default.weight.value"));
                    } catch (NumberFormatException ne) {
                        Debug.logWarning("Default shippable weight not configured (shipment.default.weight.value)", module);
                        packageWeight = BigDecimal.ONE;
                    }
                }
                // convert weight
                String weightUomId = (String) shipmentPackage.get("weightUomId");
                if (weightUomId == null) {
                    Debug.logWarning("Shipment Route Segment missing weightUomId in shipmentId " + shipmentId,  module);
                    weightUomId = "WT_lb"; // TODO: this should be specified in a properties file
                }
                results = dispatcher.runSync("convertUom", UtilMisc.<String, Object>toMap("uomId", weightUomId, "uomIdTo", DHL_WEIGHT_UOM_ID, "originalValue", packageWeight));
                if ((results == null) || (results.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_ERROR)) || (results.get("convertedValue") == null)) {
                    Debug.logWarning("Unable to convert weights for shipmentId " + shipmentId , module);
                    packageWeight = BigDecimal.ONE;
                } else {
                    packageWeight = (BigDecimal) results.get("convertedValue");
                }
            }

            // pick which weight to use and round it
            BigDecimal weight = null;
            if (hasBillingWeight) {
                weight = billingWeight;
            } else {
                weight = packageWeight;
            }
            // want the rounded weight as a string, so we use the "" + int shortcut
            String roundedWeight = weight.setScale(0, BigDecimal.ROUND_HALF_UP).toPlainString();

            // translate shipmentMethodTypeId to DHL service code
            String shipmentMethodTypeId = shipmentRouteSegment.getString("shipmentMethodTypeId");
            String dhlShipmentDetailCode = null;
            GenericValue carrierShipmentMethod = delegator.findOne("CarrierShipmentMethod", UtilMisc.toMap("shipmentMethodTypeId", shipmentMethodTypeId,
                    "partyId", "DHL", "roleTypeId", "CARRIER"), false);
            if (carrierShipmentMethod == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentDhlNoCarrierShipmentMethod", 
                        UtilMisc.toMap("carrierPartyId", "DHL", "shipmentMethodTypeId", shipmentMethodTypeId), locale));
            }
            dhlShipmentDetailCode = carrierShipmentMethod.getString("carrierServiceCode");

            // shipping credentials (configured in properties)
            String userid = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessUserId", resource, "shipment.dhl.access.userid");
            String password = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessPassword", resource, "shipment.dhl.access.password");
            String shippingKey = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessShippingKey", resource, "shipment.dhl.access.shippingKey");
            String accountNbr = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessAccountNbr", resource, "shipment.dhl.access.accountNbr");
            if ((shippingKey == null) || (accountNbr == null) || (shippingKey.length() == 0) || (accountNbr.length() == 0)) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentDhlGatewayNotAvailable", locale));
            }

            // label image preference (PNG or GIF)
            String labelImagePreference = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "labelImageFormat", resource, "shipment.dhl.label.image.format");
            if (labelImagePreference == null) {
                Debug.logInfo("shipment.dhl.label.image.format not specified, assuming PNG", module);
                labelImagePreference="PNG";
            } else if (!(labelImagePreference.equals("PNG") || labelImagePreference.equals("GIF"))) {
                Debug.logError("Illegal shipment.dhl.label.image.format: " + labelImagePreference, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentDhlUnknownLabelImageFormat", 
                        UtilMisc.toMap("labelImagePreference", labelImagePreference), locale));
            }

            // create AccessRequest XML doc using FreeMarker template
            String templateName = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "rateEstimateTemplate", resource, "shipment.dhl.template.rate.estimate");
            if ((templateName == null) || (templateName.trim().length() == 0)) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentDhlRateEstimateTemplateNotConfigured", locale));
            }
            StringWriter outWriter = new StringWriter();
            Map<String, Object> inContext = FastMap.newInstance();
            inContext.put("action", "GenerateLabel");
            inContext.put("userid", userid);
            inContext.put("password", password);
            inContext.put("accountNbr", accountNbr);
            inContext.put("shippingKey", shippingKey);
            inContext.put("shipDate", UtilDateTime.nowTimestamp());
            inContext.put("dhlShipmentDetailCode", dhlShipmentDetailCode);
            inContext.put("weight", roundedWeight);
            inContext.put("senderPhoneNbr", originPhoneNumber);
            inContext.put("companyName", destPostalAddress.getString("toName"));
            inContext.put("attnTo", destPostalAddress.getString("attnName"));
            inContext.put("street", destPostalAddress.getString("address1"));
            inContext.put("streetLine2", destPostalAddress.getString("address2"));
            inContext.put("city", destPostalAddress.getString("city"));
            inContext.put("state", destPostalAddress.getString("stateProvinceGeoId"));
            
            // DHL ShipIT API does not accept ZIP+4
            if ((destPostalAddress.getString("postalCode") != null) && (destPostalAddress.getString("postalCode").length() > 5)) {
                inContext.put("postalCode", destPostalAddress.getString("postalCode").substring(0,5));
            } else {
                inContext.put("postalCode", destPostalAddress.getString("postalCode"));
            }
            inContext.put("phoneNbr", destPhoneNumber);
            inContext.put("labelImageType", labelImagePreference);
            inContext.put("shipperReference", shipment.getString("primaryOrderId") + "-" + shipment.getString("primaryShipGroupSeqId"));
            inContext.put("notifyEmailAddress", recipientEmail);

            try {
                ContentWorker.renderContentAsText(dispatcher, delegator, templateName, outWriter, inContext, locale, "text/plain", null, null, false);
            } catch (Exception e) {
                Debug.logError(e, "Cannot confirm DHL shipment: Failed to render DHL XML Request.", module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentFedexRateTemplateRenderingError", locale));
            }
            String requestString = outWriter.toString();
            if (Debug.verboseOn()) {
                Debug.logVerbose(requestString, module);
            }

            // send the request
            String responseString = null;
            try {
                responseString = sendDhlRequest(requestString, delegator, shipmentGatewayConfigId, resource, locale);
                if (Debug.verboseOn()) {
                    Debug.logVerbose(responseString, module);
                }
            } catch (DhlConnectException e) {
                String uceErrMsg = "Error sending DHL request for DHL Service Rate: " + e.toString();
                Debug.logError(e, uceErrMsg, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentFedexRateTemplateSendingError", 
                        UtilMisc.toMap("errorString", e.toString()), locale));
            }
            // pass to handler method
            return handleDhlShipmentConfirmResponse(responseString, shipmentRouteSegment, shipmentPackageRouteSegs, locale);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            if (shipmentConfirmResponseString != null) {
                Debug.logError("Got XML ShipmentConfirmRespose: " + shipmentConfirmResponseString, module);
                return ServiceUtil.returnError(UtilMisc.toList(
                        UtilProperties.getMessage(resourceError, 
                                "FacilityShipmentFedexRateTemplateReadingError", 
                                UtilMisc.toMap("errorString", e.toString()), locale),
                        UtilProperties.getMessage(resourceError, 
                                "FacilityShipmentFedexShipmentConfirmResponse", 
                                UtilMisc.toMap("shipmentConfirmResponseString", shipmentConfirmResponseString), locale)));
            } else {
                return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                        "FacilityShipmentFedexRateTemplateReadingError", 
                        UtilMisc.toMap("errorString", e.toString()), locale));
            }
        } catch (GenericServiceException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentFedexRateTemplateReadingError", 
                    UtilMisc.toMap("errorString", e.toString()), locale));
        }
    }

    // NOTE: Must VOID shipments on errors
    public static Map<String, Object> handleDhlShipmentConfirmResponse(String rateResponseString, GenericValue shipmentRouteSegment,
            List<GenericValue> shipmentPackageRouteSegs, Locale locale) throws GenericEntityException {
        GenericValue shipmentPackageRouteSeg = shipmentPackageRouteSegs.get(0);

        // TODO: figure out how to handle validation on return XML, which can be mangled
        // Ideas: try again right away, let user try again, etc.
        Document rateResponseDocument = null;
        try {
            rateResponseDocument = UtilXml.readXmlDocument(rateResponseString, false);
        } catch (SAXException e2) {
            String excErrMsg = "Error parsing the RatingServiceSelectionResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            // TODO: VOID
        } catch (ParserConfigurationException e2) {
            String excErrMsg = "Error parsing the RatingServiceSelectionResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            // TODO VOID
        } catch (IOException e2) {
            String excErrMsg = "Error parsing the RatingServiceSelectionResponse: " + e2.toString();
            Debug.logError(e2, excErrMsg, module);
            // TODO VOID
        }

        // tracking number: Shipment/ShipmentDetail/AirbillNbr
        Element rootElement = rateResponseDocument.getDocumentElement();
        Element shipmentElement = UtilXml.firstChildElement(rootElement, "Shipment");
        Element shipmentDetailElement = UtilXml.firstChildElement(shipmentElement, "ShipmentDetail");
        String trackingNumber = UtilXml.childElementValue(shipmentDetailElement, "AirbillNbr");

        // label: Shipment/Label/Image
        Element labelElement = UtilXml.firstChildElement(shipmentElement, "Label");
        String encodedImageString = UtilXml.childElementValue(labelElement, "Image");
        if (encodedImageString == null) {
            Debug.logError("Cannot find response DHL shipment label.  Rate response document is: " + rateResponseString, module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resourceError, 
                    "FacilityShipmentDhlShipmentLabelError", 
                    UtilMisc.toMap("shipmentPackageRouteSeg", shipmentPackageRouteSeg, 
                            "rateResponseString", rateResponseString), locale));
        }

        // TODO: this is a temporary hack to replace the newlines so that Base64 likes the input This is NOT platform independent
        int size = encodedImageString.length();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < size; i++) {
            if (encodedImageString.charAt(i) == '\n')
                continue;
            sb.append(encodedImageString.charAt(i));
        }
        byte[] labelBytes = Base64.base64Decode(sb.toString().getBytes());

        if (labelBytes != null) {
            // store in db blob
            shipmentPackageRouteSeg.setBytes("labelImage", labelBytes);
        } else {
            Debug.logInfo("Failed to either decode returned DHL label or no data found in eCommerce/Shipment/Label/Image.", module);
            // TODO: VOID
        }

        shipmentPackageRouteSeg.set("trackingCode", trackingNumber);
        shipmentPackageRouteSeg.set("labelHtml", sb.toString());
        shipmentPackageRouteSeg.store();

        shipmentRouteSegment.set("trackingIdNumber", trackingNumber);
        shipmentRouteSegment.put("carrierServiceStatusId", "SHRSCS_CONFIRMED");
        shipmentRouteSegment.store();

        return ServiceUtil.returnSuccess(UtilProperties.getMessage(resourceError, 
                "FacilityShipmentDhlShipmentConfirmed", locale));
    }

    /*
    private static BigDecimal getWeight(List<Map<String, Object>> shippableItemInfo) {
        BigDecimal totalWeight = BigDecimal.ZERO;
        if (shippableItemInfo != null) {
            for (Map<String, Object> itemInfo: shippableItemInfo) {
                BigDecimal weight = ((BigDecimal) itemInfo.get("weight"));
                totalWeight = totalWeight.add(weight);
            }
        }
        return totalWeight;
    }
    */

    public static Document createAccessRequestDocument(Delegator delegator, String shipmentGatewayConfigId, String resource) {
        Document eCommerceRequestDocument = UtilXml.makeEmptyXmlDocument("eCommerce");
        Element eCommerceRequesElement = eCommerceRequestDocument.getDocumentElement();
        eCommerceRequesElement.setAttribute("version", getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "headVersion", resource, "shipment.dhl.head.version"));
        eCommerceRequesElement.setAttribute("action", getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "headAction", resource, "shipment.dhl.head.action"));
        Element requestorRequestElement = UtilXml.addChildElement(eCommerceRequesElement, "Requestor", eCommerceRequestDocument);
        UtilXml.addChildElementValue(requestorRequestElement, "ID", getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessUserId", resource, "shipment.dhl.access.userid"),
                eCommerceRequestDocument);
        UtilXml.addChildElementValue(requestorRequestElement, "Password", getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, "accessPassword", resource, "shipment.dhl.access.password"),
                eCommerceRequestDocument);
        return eCommerceRequestDocument;
    }
    
    public static void handleErrors(Element responseElement, List<Object> errorList, Locale locale) {
        Element faultsElement = UtilXml.firstChildElement(responseElement,
                "Faults");
        List<? extends Element> faultElements = UtilXml.childElementList(faultsElement, "Fault");
        if (UtilValidate.isNotEmpty(faultElements)) {
            for (Element errorElement: faultElements) {
                StringBuilder errorMessageBuf = new StringBuilder();

                String errorCode = UtilXml.childElementValue(errorElement, "Code");
                String errorDescription = UtilXml.childElementValue(errorElement, "Desc");
                String errorSource = UtilXml.childElementValue(errorElement, "Source");
                if (UtilValidate.isEmpty(errorSource)) {
                    errorSource = UtilXml.childElementValue(errorElement, "Context");
                }
                errorMessageBuf.append(UtilProperties.getMessage(resourceError, "FacilityShipmentDhlErrorMessage", 
                        UtilMisc.toMap("errorCode", errorCode, "errorDescription", errorDescription), locale));
                if (UtilValidate.isNotEmpty(errorSource)) {
                    errorMessageBuf.append(UtilProperties.getMessage(resourceError, 
                            "FacilityShipmentDhlErrorMessageElement", 
                            UtilMisc.toMap("errorSource", errorSource), locale));
                }
                errorList.add(errorMessageBuf.toString());
            }
        }
    }
    
    private static String getShipmentGatewayConfigValue(Delegator delegator, String shipmentGatewayConfigId, String shipmentGatewayConfigParameterName,
                                                        String resource, String parameterName) {
        String returnValue = "";
        if (UtilValidate.isNotEmpty(shipmentGatewayConfigId)) {
            try {
                GenericValue dhl = delegator.findOne("ShipmentGatewayDhl", UtilMisc.toMap("shipmentGatewayConfigId", shipmentGatewayConfigId), false);
                if (UtilValidate.isNotEmpty(dhl)) {
                    Object dhlField = dhl.get(shipmentGatewayConfigParameterName);
                    if (dhlField != null) {
                        returnValue = dhlField.toString().trim();
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }
        } else {
            String value = UtilProperties.getPropertyValue(resource, parameterName);
            if (value != null) {
                returnValue = value.trim();
            }
        }
        return returnValue;
    }
    
    private static String getShipmentGatewayConfigValue(Delegator delegator, String shipmentGatewayConfigId, String shipmentGatewayConfigParameterName,
                                                        String resource, String parameterName, String defaultValue) {
        String returnValue = getShipmentGatewayConfigValue(delegator, shipmentGatewayConfigId, shipmentGatewayConfigParameterName, resource, parameterName);
        if (UtilValidate.isEmpty(returnValue)) {
            returnValue = defaultValue;
        }
        return returnValue;
    }
}


@SuppressWarnings("serial")
class DhlConnectException extends GeneralException {
    DhlConnectException() {
        super();
    }

    DhlConnectException(String msg) {
        super(msg);
    }

    DhlConnectException(Throwable t) {
        super(t);
    }

    DhlConnectException(String msg, Throwable t) {
        super(msg, t);
    }
}
