/*
 * 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.apache.axis2.jaxws.message.util;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMSourcedElement;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPFault;
import org.apache.axiom.soap.SOAPFaultCode;
import org.apache.axiom.soap.SOAPFaultDetail;
import org.apache.axiom.soap.SOAPFaultNode;
import org.apache.axiom.soap.SOAPFaultReason;
import org.apache.axiom.soap.SOAPFaultRole;
import org.apache.axiom.soap.SOAPFaultSubCode;
import org.apache.axiom.soap.SOAPFaultText;
import org.apache.axiom.soap.SOAPFaultValue;
import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.message.Block;
import org.apache.axis2.jaxws.message.Message;
import org.apache.axis2.jaxws.message.Protocol;
import org.apache.axis2.jaxws.message.XMLFault;
import org.apache.axis2.jaxws.message.XMLFaultCode;
import org.apache.axis2.jaxws.message.XMLFaultReason;
import org.apache.axis2.jaxws.message.factory.MessageFactory;
import org.apache.axis2.jaxws.message.factory.OMBlockFactory;
import org.apache.axis2.jaxws.message.factory.SAAJConverterFactory;
import org.apache.axis2.jaxws.registry.FactoryRegistry;

import javax.xml.namespace.QName;
import javax.xml.soap.Detail;
import javax.xml.soap.DetailEntry;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import javax.xml.stream.XMLStreamException;
import javax.xml.ws.WebServiceException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

/**
 * Collection of utilities used by the Message implementation to process XMLFaults.
 *
 * @see XMLFault
 */
public class XMLFaultUtils {


    /**
     * @param envelope javax.xml.soap.SOAPEnvelope
     * @return true if the SOAPEnvelope contains a SOAPFault
     */
    public static boolean isFault(javax.xml.soap.SOAPEnvelope envelope) throws SOAPException {
        javax.xml.soap.SOAPBody body = envelope.getBody();
        if (body != null) {
            return (body.getFault() != null);
        }
        return false;
    }

    /**
     * @param envelope org.apache.axiom.soap.SOAPEnvelope
     * @return true if the SOAPEnvelope contains a SOAPFault
     */
    public static boolean isFault(SOAPEnvelope envelope) {
        return envelope.hasFault();
    }
    
    /**
     * @param block representing a message payload
     * @return true if the localname & namespace represent a SOAP 1.1 or SOAP 1.2 fault.
     */
    public static boolean containsFault(Block b) {
        if (b != null) {
            QName qn = b.getQName();
            if (qn != null &&
                qn.getLocalPart().equals(org.apache.axiom.soap.SOAPConstants.SOAPFAULT_LOCAL_NAME)
                && (qn.getNamespaceURI().equals(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI)
                    || qn.getNamespaceURI().equals(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI))) {
                return true;
            }
        }        
        return false;
    }


    /**
     * Create an XMLFault object from a SOAPFault and detail Blocks
     *
     * @param soapFault
     * @param detailBlocks
     * @return
     */
    public static XMLFault createXMLFault(SOAPFault soapFault, Block[] detailBlocks)
            throws WebServiceException {

        // Here is a sample comprehensive SOAP 1.2 fault which will help you 
        // understand the structure.
        // <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
        //               xmlns:m="http://www.example.org/timeouts"
        //               xmlns:xml="http://www.w3.org/XML/1998/namespace">
        //   <env:Body>
        //      <env:Fault>
        //        <env:Code>
        //          <env:Value>env:Sender</env:Value>
        //          <env:Subcode>
        //            <env:Value>m:MessageTimeout</env:Value>
        //          </env:Subcode>
        //        </env:Code>
        //        <env:Reason>
        //          <env:Text xml:lang="en">Sender Timeout</env:Text>
        //          <env:Text xml:lang="de">Sender Timeout</env:Text>
        //        </env:Reason>
        //        <env:Node>http://my.example.org/Node</env:Node>
        //        <env:Role>http://my.example.org/Role</env:Role>
        //        <env:Detail>
        //          <m:MaxTime>P5M</m:MaxTime>
        //        </env:Detail>    
        //      </env:Fault>
        //   </env:Body>
        // </env:Envelope>

        // Get the code
        // TODO what if this fails ?  Log a message and treat like a RECEIVER fault ?

        //figureout the soap version
        boolean isSoap11 = soapFault.getNamespace().getNamespaceURI().equals(
                SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);

        SOAPFaultCode soapCode = soapFault.getCode();
        QName codeQName = null;
        if (isSoap11) {
            codeQName = soapCode.getTextAsQName();
        } else {
            codeQName = soapCode.getValue().getTextAsQName();
        }
        XMLFaultCode code = XMLFaultCode.fromQName(codeQName);

        // Get the primary reason text
        // TODO what if this fails
        SOAPFaultReason soapReason = soapFault.getReason();
        String text = null;
        String lang = null;
        List soapTexts = null;
        if (isSoap11) {
            text = soapReason.getText();
        } else {
            soapTexts = soapReason.getAllSoapTexts();
            SOAPFaultText reasonText = (SOAPFaultText)soapTexts.get(0);
            text = reasonText.getText();
            lang = reasonText.getLang();
        }
        XMLFaultReason reason = new XMLFaultReason(text, lang);

        // Construct the XMLFault from the required information (code, reason, detail blocks)
        XMLFault xmlFault = new XMLFault(code, reason, detailBlocks);

        // Add the secondary fault information

        // Get the SubCodes
        SOAPFaultSubCode soapSubCode = soapCode.getSubCode();
        if (soapSubCode != null) {
            List<QName> list = new ArrayList<QName>();

            // Walk the nested sub codes and collect the qnames
            while (soapSubCode != null) {
                SOAPFaultValue soapSubCodeValue = soapSubCode.getValue();
                QName qName = soapSubCodeValue.getTextAsQName();
                list.add(qName);
                soapSubCode = soapSubCode.getSubCode();
            }

            // Put the collected sub code qnames onto the xmlFault
            QName[] qNames = new QName[list.size()];
            xmlFault.setSubCodes(list.toArray(qNames));
        }

        // Get the secondary Reasons...the first reason was already saved as the primary reason
        if (soapTexts != null && soapTexts.size() > 1) {
            XMLFaultReason[] secondaryReasons = new XMLFaultReason[soapTexts.size() - 1];
            for (int i = 1; i < soapTexts.size(); i++) {
                SOAPFaultText soapReasonText = (SOAPFaultText)soapTexts.get(i);
                secondaryReasons[i - 1] = new XMLFaultReason(soapReasonText.getText(),
                                                             soapReasonText.getLang());
            }
            xmlFault.setSecondaryReasons(secondaryReasons);
        }

        // Get the Node
        SOAPFaultNode soapNode = soapFault.getNode();
        if (soapNode != null) {
            xmlFault.setNode(soapNode.getText());
        }

        // Get the Role
        SOAPFaultRole soapRole = soapFault.getRole();
        if (soapRole != null) {
            xmlFault.setRole(soapRole.getText());
        }
        return xmlFault;
    }

    /**
     * Create XMLFault
     *
     * @param soapFault
     * @return xmlFault
     * @throws WebServiceException
     */
    public static XMLFault createXMLFault(javax.xml.soap.SOAPFault soapFault)
            throws WebServiceException {
        Block[] detailBlocks = getDetailBlocks(soapFault);
        return createXMLFault(soapFault, detailBlocks);
    }

    /**
     * Create an XMLFault object from a SOAPFault and detail Blocks
     *
     * @param soapFault
     * @param detailBlocks
     * @return
     */
    public static XMLFault createXMLFault(javax.xml.soap.SOAPFault soapFault, Block[] detailBlocks)
            throws WebServiceException {

        // The SOAPFault structure is modeled after SOAP 1.2.  
        // Here is a sample comprehensive SOAP 1.2 fault which will help you understand the
        // structure.
        // <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
        //               xmlns:m="http://www.example.org/timeouts"
        //               xmlns:xml="http://www.w3.org/XML/1998/namespace">
        //   <env:Body>
        //      <env:Fault>
        //        <env:Code>
        //          <env:Value>env:Sender</env:Value>
        //          <env:Subcode>
        //            <env:Value>m:MessageTimeout</env:Value>
        //          </env:Subcode>
        //        </env:Code>
        //        <env:Reason>
        //          <env:Text xml:lang="en">Sender Timeout</env:Text>
        //          <env:Text xml:lang="de">Sender Timeout</env:Text>
        //        </env:Reason>
        //        <env:Node>http://my.example.org/Node</env:Node>
        //        <env:Role>http://my.example.org/Role</env:Role>
        //        <env:Detail>
        //          <m:MaxTime>P5M</m:MaxTime>
        //        </env:Detail>    
        //      </env:Fault>
        //   </env:Body>
        // </env:Envelope>

        // Get the code or default code
        QName codeQName = soapFault.getFaultCodeAsQName();
        XMLFaultCode code = XMLFaultCode.fromQName(codeQName);

        // Get the primary reason text
        // TODO what if this fails
        String text = soapFault.getFaultString();
        Locale locale = soapFault.getFaultStringLocale();
        XMLFaultReason reason = new XMLFaultReason(text, localeToXmlLang(locale));

        // Construct the XMLFault from the required information (code, reason, detail blocks)
        XMLFault xmlFault = new XMLFault(code, reason, detailBlocks);


        boolean isSOAP12 =
                soapFault.getNamespaceURI().equals(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE);

        // Add the secondary fault information

        // Get the SubCodes
        if (isSOAP12) {
            Iterator it = soapFault.getFaultSubcodes();
            List<QName> list = new ArrayList<QName>();
            while (it.hasNext()) {
                QName qName = (QName)it.next();
                list.add(qName);
            }
            if (list.size() > 0) {
                QName[] subCodes = new QName[list.size()];
                subCodes = list.toArray(subCodes);
                xmlFault.setSubCodes(subCodes);
            }
        }

        // Get the secondary Reasons...the first reason was already saved as the primary reason
        if (isSOAP12) {
            try {
                Iterator it = soapFault.getFaultReasonLocales();
                boolean first = true;
                List<XMLFaultReason> list = new ArrayList<XMLFaultReason>();
                while (it.hasNext()) {
                    locale = (Locale)it.next();
                    if (first) {
                        first = false;
                    } else {
                        text = soapFault.getFaultReasonText(locale);
                        list.add(new XMLFaultReason(text, localeToXmlLang(locale)));
                    }
                }
                if (list.size() > 0) {
                    XMLFaultReason[] secondaryReasons = new XMLFaultReason[list.size()];
                    secondaryReasons = list.toArray(secondaryReasons);
                    xmlFault.setSecondaryReasons(secondaryReasons);
                }
            } catch (SOAPException se) {
                throw ExceptionFactory.makeWebServiceException(se);
            }
        }

        // Get the Node
        if (isSOAP12) {
            String soapNode = soapFault.getFaultNode();
            if (soapNode != null) {
                xmlFault.setNode(soapNode);
            }
        }

        // Get the Role
        String soapRole = soapFault
                .getFaultActor();  // getFaultActor works for both SOAP 1.1 and SOAP 1.2 per spec
        if (soapRole != null) {
            xmlFault.setRole(soapRole);
        }

        return xmlFault;
    }

    public static XMLFault createXMLFault(Block b, Protocol p) {
        // Because of the requirement that we have a full SOAP envelope structure as
        // the input to the StAXSOAPModelBuilder, we have to have a dummy envelope
        // that wraps our fault.  This will allow the Axiom SOAPFault object to
        // be created.        
        Message m = null;
        try {
            MessageFactory mf = (MessageFactory) FactoryRegistry.getFactory(MessageFactory.class);
            m = mf.create(p);
            m.setBodyBlock(b);
        } catch (XMLStreamException e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
        
        SOAPEnvelope dummyEnv = (SOAPEnvelope) m.getAsOMElement();        
        
        StAXSOAPModelBuilder builder = new StAXSOAPModelBuilder(dummyEnv.getXMLStreamReaderWithoutCaching());
        SOAPEnvelope newEnv = (SOAPEnvelope) builder.getDocumentElement();
        
        SOAPBody body = newEnv.getBody();
        SOAPFault fault = body.getFault();
        
        Block[] details = getDetailBlocks(fault);
        
        return XMLFaultUtils.createXMLFault(fault, details);
    }
    
    private static Block[] getDetailBlocks(SOAPFault soapFault) throws WebServiceException {
        try {
            Block[] blocks = null;
            SOAPFaultDetail detail = soapFault.getDetail();
            if (detail != null) {
                // Create a block for each element
                OMBlockFactory bf =
                        (OMBlockFactory) FactoryRegistry.getFactory(OMBlockFactory.class);
                ArrayList<Block> list = new ArrayList<Block>();
                Iterator it = detail.getChildElements();
                while (it.hasNext()) {
                    OMElement om = (OMElement) it.next();
                    Block b = bf.createFrom(om, null, om.getQName());
                    list.add(b);
                }
                blocks = new Block[list.size()];
                blocks = list.toArray(blocks);
            }
            return blocks;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    private static Block[] getDetailBlocks(javax.xml.soap.SOAPFault soapFault)
            throws WebServiceException {
        try {
            Block[] blocks = null;
            Detail detail = soapFault.getDetail();
            if (detail != null) {
                // Get a SAAJ->OM converter
                SAAJConverterFactory converterFactory = (SAAJConverterFactory)FactoryRegistry
                        .getFactory(SAAJConverterFactory.class);
                SAAJConverter converter = converterFactory.getSAAJConverter();

                // Create a block for each element
                OMBlockFactory bf =
                        (OMBlockFactory)FactoryRegistry.getFactory(OMBlockFactory.class);
                ArrayList<Block> list = new ArrayList<Block>();
                Iterator it = detail.getDetailEntries();
                while (it.hasNext()) {
                    DetailEntry de = (DetailEntry)it.next();
                    OMElement om = converter.toOM(de);
                    Block b = bf.createFrom(om, null, om.getQName());
                    list.add(b);
                }
                blocks = new Block[list.size()];
                blocks = list.toArray(blocks);
            }
            return blocks;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    /**
     * Create a SOAPFault representing the XMLFault and attach it to body. If there are 1 or more
     * detail Blocks on the XMLFault, a SOAPFaultDetail is attached. If ignoreDetailBlocks=false,
     * then OMElements are added to the SOAPFaultDetail. If ignoreDetailBlocks=true, then the Detail
     * Blocks are ignored (this is necessary for XMLSpine processing)
     *
     * @param xmlFault
     * @param body               - Assumes that the body is empty
     * @param ignoreDetailBlocks true or fals
     * @return SOAPFault (which is attached to body)
     */
    public static SOAPFault createSOAPFault(XMLFault xmlFault,
                                            SOAPBody body,
                                            boolean ignoreDetailBlocks) throws WebServiceException {

        // Get the factory and create the soapFault
        SOAPFactory factory = (SOAPFactory)body.getOMFactory();
        SOAPFault soapFault = factory.createSOAPFault(body);
        OMNamespace ns = body.getNamespace();

        // The SOAPFault structure is modeled after SOAP 1.2.  
        // Here is a sample comprehensive SOAP 1.2 fault which will help you understand the
        // structure.
        // <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
        //               xmlns:m="http://www.example.org/timeouts"
        //               xmlns:xml="http://www.w3.org/XML/1998/namespace">
        //   <env:Body>
        //      <env:Fault>
        //        <env:Code>
        //          <env:Value>env:Sender</env:Value>
        //          <env:Subcode>
        //            <env:Value>m:MessageTimeout</env:Value>
        //          </env:Subcode>
        //        </env:Code>
        //        <env:Reason>
        //          <env:Text xml:lang="en">Sender Timeout</env:Text>
        //          <env:Text xml:lang="de">Sender Timeout</env:Text>
        //        </env:Reason>
        //        <env:Node>http://my.example.org/Node</env:Node>
        //        <env:Role>http://my.example.org/Role</env:Role>
        //        <env:Detail>
        //          <m:MaxTime>P5M</m:MaxTime>
        //        </env:Detail>    
        //      </env:Fault>
        //   </env:Body>
        // </env:Envelope>

        boolean isSoap11 = soapFault.getNamespace().getNamespaceURI()
                .equals(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);

        // Set the primary Code Value
        SOAPFaultCode soapCode = factory.createSOAPFaultCode(soapFault);
        QName soapValueQName = xmlFault.getCode().toQName(ns.getNamespaceURI());
        if (isSoap11) {
            soapCode.setText(soapValueQName);
        } else {
            SOAPFaultValue soapValue = factory.createSOAPFaultValue(soapCode);
            soapValue.setText(soapValueQName);
        }

        // Set the primary Reason Text
        SOAPFaultReason soapReason = factory.createSOAPFaultReason(soapFault);
        if (isSoap11) {
            soapReason.setText(xmlFault.getReason().getText());
        } else {
            SOAPFaultText soapText = factory.createSOAPFaultText(soapReason);
            soapText.setText(xmlFault.getReason().getText());
            soapText.setLang(xmlFault.getReason().getLang());
        }

        // Set the Detail and contents of Detail
        Block[] blocks = xmlFault.getDetailBlocks();
        if (blocks != null && blocks.length > 0) {
            SOAPFaultDetail detail = factory.createSOAPFaultDetail(soapFault);
            if (!ignoreDetailBlocks) {
                for (int i = 0; i < blocks.length; i++) {
                    // A Block implements OMDataSource.  So create OMSourcedElements
                    // for each of the Blocks.
                    OMSourcedElement element =
                            factory.createOMElement(blocks[i], blocks[i].getQName());
                    detail.addChild(element);
                }
            }
        }

        // Now set all of the secondary fault information
        // Set the SubCodes
        QName[] subCodes = xmlFault.getSubCodes();
        if (subCodes != null && subCodes.length > 0) {
            OMElement curr = soapCode;
            for (int i = 0; i < subCodes.length; i++) {
                SOAPFaultSubCode subCode = (i == 0) ?
                        factory.createSOAPFaultSubCode((SOAPFaultCode)curr) :
                        factory.createSOAPFaultSubCode((SOAPFaultSubCode)curr);
                SOAPFaultValue soapSubCodeValue = factory.createSOAPFaultValue(subCode);
                soapSubCodeValue.setText(subCodes[i]);
                curr = subCode;
            }
        }

        // Set the secondary reasons and languages
        XMLFaultReason reasons[] = xmlFault.getSecondaryReasons();
        if (reasons != null && reasons.length > 0) {
            for (int i = 0; i < reasons.length; i++) {
                SOAPFaultText soapReasonText = factory.createSOAPFaultText(soapReason);
                soapReasonText.setText(reasons[i].getText());
                soapReasonText.setLang(reasons[i].getLang());
            }
        }

        // Set the Role
        if (xmlFault.getRole() != null) {
            SOAPFaultRole soapRole = factory.createSOAPFaultRole();
            soapRole.setText(xmlFault.getRole());
            soapFault.setRole(soapRole);
        }

        // Set the Node
        if (xmlFault.getNode() != null) {
            SOAPFaultNode soapNode = factory.createSOAPFaultNode();
            soapNode.setText(xmlFault.getNode());
            soapFault.setNode(soapNode);
        }

        return soapFault;

    }


    /**
     * Create a SOAPFault representing the XMLFault. If there are 1 or more detail Blocks on the
     * XMLFault, a SOAPFaultDetail is attached.
     *
     * @param xmlFault
     * @param body
     * @return SOAPFault (which is attached to body)
     */
    public static javax.xml.soap.SOAPFault createSAAJFault(XMLFault xmlFault,
                                                           javax.xml.soap.SOAPBody body)
            throws SOAPException, WebServiceException {

        // Get the factory and create the soapFault
        String protocolNS = body.getNamespaceURI();

        javax.xml.soap.SOAPFault soapFault = body.addFault();

        // The SOAPFault structure is modeled after SOAP 1.2.  
        // Here is a sample comprehensive SOAP 1.2 fault which will help you understand the
        // structure.
        // <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
        //               xmlns:m="http://www.example.org/timeouts"
        //               xmlns:xml="http://www.w3.org/XML/1998/namespace">
        //   <env:Body>
        //      <env:Fault>
        //        <env:Code>
        //          <env:Value>env:Sender</env:Value>
        //          <env:Subcode>
        //            <env:Value>m:MessageTimeout</env:Value>
        //          </env:Subcode>
        //        </env:Code>
        //        <env:Reason>
        //          <env:Text xml:lang="en">Sender Timeout</env:Text>
        //          <env:Text xml:lang="de">Sender Timeout</env:Text>
        //        </env:Reason>
        //        <env:Node>http://my.example.org/Node</env:Node>
        //        <env:Role>http://my.example.org/Role</env:Role>
        //        <env:Detail>
        //          <m:MaxTime>P5M</m:MaxTime>
        //        </env:Detail>    
        //      </env:Fault>
        //   </env:Body>
        // </env:Envelope>

        // Set the primary Code Value
        QName soapValueQName = xmlFault.getCode().toQName(protocolNS);
        String prefix = soapFault.getPrefix();
        String soapValue = null;
        if (prefix == null || prefix.length() == 0) {
            soapValue = soapValueQName.getLocalPart();
        } else {
            soapValue = prefix + ":" + soapValueQName.getLocalPart();
        }
        soapFault.setFaultCode(soapValue);

        // Set the primary Reason Text
        String reasonText = xmlFault.getReason().getText();
        String reasonLang = xmlFault.getReason().getLang();
        Locale locale = (reasonLang != null && reasonLang.length() > 0) ?
                new Locale(reasonLang) :
                Locale.getDefault();
        soapFault.setFaultString(reasonText, locale);

        // Set the Detail and contents of Detail
        Block[] blocks = xmlFault.getDetailBlocks();
        if (blocks != null && blocks.length > 0) {
            Detail detail = soapFault.addDetail();
            // Get a OM->SAAJ converter
            SAAJConverterFactory converterFactory =
                    (SAAJConverterFactory)FactoryRegistry.getFactory(SAAJConverterFactory.class);
            SAAJConverter converter = converterFactory.getSAAJConverter();
            for (int i = 0; i < blocks.length; i++) {
                try {
                    converter.toSAAJ(blocks[i].getOMElement(), detail);
                } catch (XMLStreamException xse) {
                    throw ExceptionFactory.makeWebServiceException(xse);
                }
            }

        }

        // Now set all of the secondary fault information
        // Set the SubCodes
        QName[] subCodes = xmlFault.getSubCodes();
        if (subCodes != null && subCodes.length > 0 &&
                protocolNS.equals(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE)) {
            for (int i = 0; i < subCodes.length; i++) {
                soapFault.appendFaultSubcode(subCodes[i]);
            }
        }

        // Set the secondary reasons and languages
        XMLFaultReason reasons[] = xmlFault.getSecondaryReasons();
        if (reasons != null && reasons.length > 0 &&
                protocolNS.equals(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE)) {
            for (int i = 0; i < reasons.length; i++) {
                if (reasons[i].getLang() == null || reasons[i].getLang().length() == 0) {
                    locale = Locale.getDefault();
                } else {
                    locale = new Locale(reasons[i].getLang());
                }
                soapFault.addFaultReasonText(reasons[i].getText(), locale);
            }
        }

        // Set the Role
        if (xmlFault.getRole() != null) {
            soapFault.setFaultActor(
                    xmlFault.getRole());  // Use Fault actor because it is applicable for SOAP 1.1 and SOAP 1.2
        }

        // Set the Node...only applicable for SOAP 1.2
        if (xmlFault.getNode() != null && protocolNS.equals(SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE))
        {
            soapFault.setFaultNode(xmlFault.getNode());
        }

        return soapFault;

    }
    
    /**
     * Converte a Locale object to an xmlLang String
     * @param locale
     * @return String of the form <locale.getLanguage()>-<locale.getCountry()>
     */
    private static String localeToXmlLang(Locale locale) {
        if (locale == null) {
            return Locale.getDefault().getLanguage() + "-" + Locale.getDefault().getCountry();
        }
        String lang = locale.getLanguage();
        String countryCode = locale.getCountry();
        if (countryCode == null || countryCode.length() == 0) {
            return lang;
        } else {
            return new String(lang + "-" + countryCode);
        }
        
    }
}
