/*
 * 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.addressing;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.util.StAXUtils;
import org.apache.axiom.om.util.UUIDGenerator;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.externalize.ExternalizeConstants;
import org.apache.axis2.context.externalize.SafeObjectInputStream;
import org.apache.axis2.context.externalize.SafeObjectOutputStream;
import org.apache.axis2.context.externalize.SafeSerializable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Class EndpointReference
 * This class models the WS-A EndpointReferenceType. But this can be used without any WS-A handlers as well
 * Since the models for this in Submission and Final versions are different, lets make this to comply with
 * WS-A Final version. So any information found with WS-A submission will be "pumped" in to this model.
 */
public class EndpointReference implements Externalizable, SafeSerializable {

    private static final long serialVersionUID = 5278892171162372439L;

    private static final Log log = LogFactory.getLog(EndpointReference.class);
    
    //  supported revision levels, add a new level to manage compatible changes
    private static final int REVISION_2 = 2;
    // current revision level of this object
    private static final int revisionID = REVISION_2;

    private static final String myClassName = "EndpointReference";

    /**
     * An ID which can be used to correlate operations on an instance of
     * this object in the log files
     */
    private String logCorrelationIDString;
    
    /**
     * The list of URIs that should be considered equivalent to 
     * the WS-Addressing anonymous URI
     */
    private static volatile List<String> anonymousEquivalentURIs = new ArrayList<String>();


    /**
     * <EndpointReference>
     * <Address>xs:anyURI</Address>
     * <ReferenceParameters>xs:any*</ReferenceParameters>
     * <MetaData>xs:any*</MetaData>
     * <!-- In addition to this, EPR can contain any number of OMElements -->
     * </EndpointReference>
     */

    private String name;
    private String address;
    private ArrayList<OMAttribute> addressAttributes;
    private ArrayList<OMNode> metaData;
    private ArrayList<OMAttribute> metaDataAttributes;
    private Map<QName, OMElement> referenceParameters;
    private ArrayList<OMElement> extensibleElements;
    private ArrayList<OMAttribute> attributes;

    /**
     * No-Arg Constructor
     * Required for Externalizable objects
     */
    public EndpointReference() {}
    
    /**
     * Adds a parameter to the list of anonymous equivalent URIs. 
     * @param anonymousEquivalentURI any URI that has an address that
     * begins with this value will be considered to be anonymous
     */
    public static void addAnonymousEquivalentURI(String anonymousEquivalentURI){
        if (log.isTraceEnabled())
        	log.trace("addAnonymousEquivalentURI: " + anonymousEquivalentURI);
        
        // Avoid synchronization in hasAnonymousAddress by using the
        // technique outlined at http://is.gd/gv3
        synchronized (anonymousEquivalentURIs) {
        	ArrayList<String> newList = new ArrayList<String>(anonymousEquivalentURIs);
        	newList.add(anonymousEquivalentURI);
            anonymousEquivalentURIs = newList;
        }
    }
 

    /**
     * @param address
     */
    public EndpointReference(String address) {
        this.address = address;
    }

    /**
     * @param omElement
     */
    public void addReferenceParameter(OMElement omElement) {
        if (omElement == null) {
            return;
        }
        if (referenceParameters == null) {
            referenceParameters = new HashMap<QName, OMElement>();
        }
        referenceParameters.put(omElement.getQName(), omElement);
    }

    /**
     * @param qname
     * @param value - the text of the OMElement. Remember that this is a convenient method for the user,
     *              which has limited capability. If you want more power use @See EndpointReference#addReferenceParameter(OMElement)
     */
    public void addReferenceParameter(QName qname, String value) {
        if (qname == null) {
            return;
        }
        OMElement omElement = OMAbstractFactory.getOMFactory().createOMElement(qname, null);
        omElement.setText(value);
        addReferenceParameter(omElement);
    }

    /**
     * This will return a Map of reference parameters with QName as the key and an OMElement
     * as the value
     *
     * @return - map of the reference parameters, where the key is the QName of the reference parameter
     *         and the value is an OMElement
     */
    public Map<QName, OMElement> getAllReferenceParameters() {
        return referenceParameters;
    }

    public String getAddress() {
        return address;
    }

    /**
     * @param address - xs:anyURI
     */
    public void setAddress(String address) {
        this.address = address;
    }

    public ArrayList<OMAttribute> getAddressAttributes() {
        return addressAttributes;
    }

    public void setAddressAttributes(ArrayList<OMAttribute> al) {
        addressAttributes = al;
    }

    public ArrayList<OMAttribute> getMetadataAttributes() {
        return metaDataAttributes;
    }

    public void setMetadataAttributes(ArrayList<OMAttribute> al) {
        metaDataAttributes = al;
    }
    
    /** 
     * This method identifies whether the address is a WS-Addressing spec defined
     * anonymous URI.
     * 
     * @return true if the address is a WS-Addressing spec defined anonymous URI.
     * 
     * @see #hasAnonymousAddress()
     */ 
    public boolean isWSAddressingAnonymous() {
        return (AddressingConstants.Final.WSA_ANONYMOUS_URL.equals(address) ||
                AddressingConstants.Submission.WSA_ANONYMOUS_URL.equals(address));
    }
    
    /**
     * This method is used to identify when response messages should be sent using
     * the back channel of a two-way transport.
     *
     * @return true if the address is a WS-Addressing spec defined anonymous URI,
     * or starts with a string that is specified to be equivalent to an anonymous
     * URI.
     * 
     * @see #addAnonymousEquivalentURI(String)
     */
    public boolean hasAnonymousAddress() {
        boolean result = isWSAddressingAnonymous();
        
        if(!result && address != null) {
        	// If the address is not WS-A anonymous it might still be considered anonymous
        	// Avoid synchronization by using the
            // technique outlined at http://is.gd/gv3
        	List<String> localList = anonymousEquivalentURIs;
        	if(!localList.isEmpty()){
        		Iterator<String> it = localList.iterator();
        		while(it.hasNext()){
        			result = address.startsWith((String)it.next());
        			if(result){
        				break;
        			}
        		}	
        	}    	
        }

        if (log.isTraceEnabled()) {
            log.trace("hasAnonymousAddress: " + address + " is Anonymous: " + result);
        }
        
        return result;
    }

    /**
     * hasNoneAddress
     *
     * @return true if the address is the 'None URI' from the final addressing spec.
     */
    public boolean hasNoneAddress() {
        boolean result = AddressingConstants.Final.WSA_NONE_URI.equals(address);
        if (log.isTraceEnabled()) {
            log.trace("hasNoneAddress: " + address + " is None: " + result);
        }
        return result;
    }

    /**
     * @param localName
     * @param ns
     * @param value
     */
    public void addAttribute(String localName, OMNamespace ns, String value) {
        if (attributes == null) {
            attributes = new ArrayList<OMAttribute>();
        }
        attributes.add(OMAbstractFactory.getOMFactory().createOMAttribute(localName, ns, value));
    }

    public ArrayList<OMAttribute> getAttributes() {
        return attributes;
    }


    /**
     * @param omAttribute
     */
    public void addAttribute(OMAttribute omAttribute) {
        if (attributes == null) {
            attributes = new ArrayList<OMAttribute>();
        }
        attributes.add(omAttribute);
    }

    public ArrayList<OMElement> getExtensibleElements() {
        return extensibleElements;
    }

    /**
     * {any}
     *
     * @param extensibleElements
     */
    public void setExtensibleElements(ArrayList<OMElement> extensibleElements) {
        this.extensibleElements = extensibleElements;
    }

    public void addExtensibleElement(OMElement extensibleElement) {
        if (extensibleElement != null) {
            if (this.extensibleElements == null) {
                this.extensibleElements = new ArrayList<OMElement>();
            }
            this.extensibleElements.add(extensibleElement);
        }
    }

    public ArrayList<OMNode> getMetaData() {
        return metaData;
    }

    public void addMetaData(OMNode metaData) {
        if (metaData != null) {
            if (this.metaData == null) {
                this.metaData = new ArrayList<OMNode>();
            }
            this.metaData.add(metaData);
        }

    }

    /**
     * @deprecated
     */
    public String getName() {
        return name;
    }

    /**
     * @param name
     * @deprecated
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Set a Map with QName as the key and an OMElement
     * as the value
     *
     * @param referenceParameters
     */
    public void setReferenceParameters(Map<QName, OMElement> referenceParameters) {
        this.referenceParameters = referenceParameters;
    }

    /*
    *  (non-Javadoc)
    * @see java.lang.Object#toString()
    */
    public String toString() {
        StringBuffer buffer = new StringBuffer("Address: " + address);

        if (addressAttributes != null) {
            buffer.append(", Address Attributes: ").append(addressAttributes);
        }

        if (metaData != null) {
            buffer.append(", Metadata: ").append(metaData);
        }
        
        if (metaDataAttributes != null) {
            buffer.append(", Metadata Attributes: ").append(metaDataAttributes);
        }

        if (referenceParameters != null) {
            buffer.append(", Reference Parameters: ").append(referenceParameters);
        }

        if (extensibleElements != null) {
            buffer.append(", Extensibility elements: ").append(extensibleElements);
        }

        if (attributes != null) {
            buffer.append(", Attributes: ").append(attributes);
        }

        return buffer.toString();
    }

    /**
     * @param eprOMElement
     * @deprecated use {@link EndpointReferenceHelper#fromOM(OMElement)} instead.
     */
    public void fromOM(OMElement eprOMElement) {
        OMElement addressElement = eprOMElement.getFirstChildWithName(new QName("Address"));
        setAddress(addressElement.getText());
        Iterator allAddrAttributes = addressElement.getAllAttributes();
        if (addressAttributes == null) {
            addressAttributes = new ArrayList<OMAttribute>();
        }

        while (allAddrAttributes.hasNext()) {
            OMAttribute attribute = (OMAttribute) allAddrAttributes.next();
            addressAttributes.add(attribute);
        }


        OMElement refParamElement = eprOMElement
                .getFirstChildWithName(new QName(AddressingConstants.EPR_REFERENCE_PARAMETERS));

        if (refParamElement != null) {
            Iterator refParams = refParamElement.getChildElements();
            while (refParams.hasNext()) {
                OMElement omElement = (OMElement) refParams.next();
                addReferenceParameter(omElement);
            }
        }


        OMElement metaDataElement = eprOMElement
                .getFirstChildWithName(new QName(AddressingConstants.Final.WSA_METADATA));
        if (metaDataElement != null) {
            Iterator children = metaDataElement.getChildren();
            while (children.hasNext()) {
                OMNode omNode = (OMNode) children.next();
                addMetaData(omNode);
            }
        }

        setName(eprOMElement.getLocalName());

        Iterator allAttributes = eprOMElement.getAllAttributes();
        if (attributes == null) {
            attributes = new ArrayList();
        }

        while (allAttributes.hasNext()) {
            OMAttribute attribute = (OMAttribute) allAttributes.next();
            attributes.add(attribute);
        }

        Iterator childElements = eprOMElement.getChildElements();
        while (childElements.hasNext()) {
            OMElement eprChildElement = (OMElement) childElements.next();
            String localName = eprChildElement.getLocalName();
            if (!localName.equals("Address") &&
                    !localName.equals(AddressingConstants.EPR_REFERENCE_PARAMETERS) &&
                    !localName.equals(AddressingConstants.Final.WSA_METADATA)) {
                addExtensibleElement(eprChildElement);
            }
        }
    }

    /**
     * @param nsurl
     * @param localName
     * @param prefix
     * @throws AxisFault
     * @deprecated use {@link EndpointReferenceHelper#toOM(EndpointReference, QName, String)} instead.
     */
    public OMElement toOM(String nsurl, String localName, String prefix) throws AxisFault {
        OMFactory fac = OMAbstractFactory.getOMFactory();
        if (prefix != null) {
            OMNamespace wrapNs = fac.createOMNamespace(nsurl, prefix);
            OMElement epr = fac.createOMElement(localName, wrapNs);
            OMNamespace wsaNS = fac.createOMNamespace(AddressingConstants.Final.WSA_NAMESPACE,
                                                      AddressingConstants.WSA_DEFAULT_PREFIX);
            OMElement addressE = fac.createOMElement(AddressingConstants.EPR_ADDRESS, wsaNS, epr);
            addressE.setText(address);

            if (addressAttributes != null) {
                Iterator attrIter = addressAttributes.iterator();
                while (attrIter.hasNext()) {
                    OMAttribute omAttributes = (OMAttribute) attrIter.next();
                    addressE.addAttribute(omAttributes);
                }
            }

            if (this.metaData != null) {
                OMElement metadataE =
                        fac.createOMElement(AddressingConstants.Final.WSA_METADATA, wsaNS, epr);
                Iterator metadata = this.metaData.iterator();
                while (metadata.hasNext()) {
                    metadataE.addChild((OMNode) metadata.next());
                }
            }

            if (this.referenceParameters != null) {
                OMElement refParameterElement =
                        fac.createOMElement(AddressingConstants.EPR_REFERENCE_PARAMETERS,
                                            wsaNS,
                                            epr);
                Iterator refParms = referenceParameters.values().iterator();
                while (refParms.hasNext()) {
                    refParameterElement.addChild((OMNode) refParms.next());
                }
            }

            if (attributes != null) {
                Iterator attrIter = attributes.iterator();
                while (attrIter.hasNext()) {
                    OMAttribute omAttributes = (OMAttribute) attrIter.next();
                    epr.addAttribute(omAttributes);
                }
            }

            // add xs:any
            ArrayList omElements = extensibleElements;
            if (omElements != null) {
                for (int i = 0; i < omElements.size(); i++) {
                    epr.addChild((OMElement) omElements.get(i));
                }
            }

            return epr;
        } else {
            throw new AxisFault("prefix must be specified");
        }
    }

    /**
     * Compares key parts of the state from the current instance of
     * this class with the specified instance to see if they are
     * equivalent.
     * <p/>
     * This differs from the java.lang.Object.equals() method in
     * that the equals() method generally looks at both the
     * object identity (location in memory) and the object state
     * (data).
     * <p/>
     *
     * @param epr The object to compare with
     * @return TRUE if this object is equivalent with the specified object
     *         that is, key fields match
     *         FALSE, otherwise
     */
    public boolean isEquivalent(EndpointReference epr) {
        // NOTE: the input object is expected to exist (ie, be non-null)

        if ((this.name != null) && (epr.getName() != null)) {
            if (!this.name.equals(epr.getName())) {
                return false;
            }
        } else if ((this.name == null) && (epr.getName() == null)) {
            // continue
        } else {
            // mismatch
            return false;
        }


        if ((this.address != null) && (epr.getAddress() != null)) {
            if (!this.address.equals(epr.getAddress())) {
                return false;
            }
        } else if ((this.address == null) && (epr.getAddress() == null)) {
            // continue
        } else {
            // mismatch
            return false;
        }

        // TODO: is a strict test ok to use?

        ArrayList<OMNode> eprMetaData = epr.getMetaData();

        if ((this.metaData != null) && (eprMetaData != null)) {
            if (!this.metaData.equals(eprMetaData)) {
                // This is a strict test
                // Returns true if and only if the specified object
                // is also a list, both lists have the same size, and
                // all corresponding pairs of elements in the two lists
                // are equal, ie, two lists are defined to be equal if
                // they contain the same elements in the same order.

                return false;
            }
        } else if ((this.metaData == null) && (eprMetaData == null)) {
            // keep going
        } else {
            // one of the lists is null
            return false;
        }


        ArrayList<OMElement> eprExtensibleElements = epr.getExtensibleElements();

        if ((this.extensibleElements != null) && (eprExtensibleElements != null)) {
            if (!this.extensibleElements.equals(eprExtensibleElements)) {
                // This is a strict test
                // Returns true if and only if the specified object
                // is also a list, both lists have the same size, and
                // all corresponding pairs of elements in the two lists
                // are equal, ie, two lists are defined to be equal if
                // they contain the same elements in the same order.

                return false;
            }
        } else if ((this.extensibleElements == null) && (eprExtensibleElements == null)) {
            // keep going
        } else {
            // one of the lists is null
            return false;
        }


        ArrayList<OMAttribute> eprAttributes = epr.getAttributes();

        if ((this.attributes != null) && (eprAttributes != null)) {
            if (!this.attributes.equals(eprAttributes)) {
                // This is a strict test
                // Returns true if and only if the specified object
                // is also a list, both lists have the same size, and
                // all corresponding pairs of elements in the two lists
                // are equal, ie, two lists are defined to be equal if
                // they contain the same elements in the same order.

                return false;
            }
        } else if ((this.attributes == null) && (eprAttributes == null)) {
            // keep going
        } else {
            // one of the lists is null
            return false;
        }

        // TODO: check the Map referenceParameters for equivalency

        return true;
    }

    //REVIEW: The following code is rather heavyweight, because we have to build 
    //   the OM tree -- it would probably be better to have two serialization/deserialization 
    //   paths and therefore, for trivial EPRs, store a smaller amount of info  

    /**
     * Write the EPR to the specified OutputStream.  Because of potential
     * OMElements/Attributes, we need to actually serialize the OM structures
     * (at least in some cases.)
     */
    public synchronized void writeExternal(java.io.ObjectOutput o)
            throws IOException {
        SafeObjectOutputStream out = SafeObjectOutputStream.install(o);
        
        // revision ID
        out.writeInt(revisionID);
        
        // Correlation ID
        String logCorrelationIDString = getLogCorrelationIDString();

        // String object id
        out.writeObject(logCorrelationIDString);

        // Write out the content as xml
        out.writeUTF("start xml"); // write marker
        OMElement om =
                EndpointReferenceHelper.toOM(OMAbstractFactory.getOMFactory(),
                                             this,
                                             new QName("urn:axis2", "omepr", "ser"),
                                             AddressingConstants.Final.WSA_NAMESPACE);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        try {
            om.serialize(baos);
        } catch (Exception e) {
            IOException ioe = new IOException("Unable to serialize the EndpointReference with logCorrelationID ["
                                              +logCorrelationIDString+"]"); 
            ioe.initCause(e);

            if (log.isDebugEnabled()) {
                log.debug("writeObject(): Unable to serialize the EPR with logCorrelationID ["
                          +logCorrelationIDString+"]   original error ["+e.getClass().getName()
                          +"]  message ["+e.getMessage()+"]",e);  
            }

            throw ioe;
        }

        out.writeInt(baos.size());
        out.write(baos.toByteArray());  
        out.writeUTF("end xml"); // write marker

        if (log.isDebugEnabled()) {
            byte[] buffer = baos.toByteArray();
            String content = new String(buffer);

            log.debug("writeObject(): EPR logCorrelationID ["+logCorrelationIDString+"] "    
                      +"    EPR content size ["+baos.size()+"]"
                      +"    EPR content ["+content+"]"); 
        }

    }

    /**
     * Read the EPR to the specified InputStream.
     */
    public void readExternal(java.io.ObjectInput inObject)
            throws IOException, ClassNotFoundException {
        SafeObjectInputStream in = SafeObjectInputStream.install(inObject);
        
        // revision ID
        int revID = in.readInt();
        
        // make sure the object data is in a revision level we can handle
        if (revID != REVISION_2) {
            throw new ClassNotFoundException(ExternalizeConstants.UNSUPPORTED_REVID);
        }
        
        // String object id
        logCorrelationIDString = (String) in.readObject();

        // Read xml content
        in.readUTF(); // read marker
        int numBytes = in.readInt();

        byte[] serBytes = new byte[numBytes];

        // read the data from the input stream

        int bytesRead = 0;
        int numberOfBytesLastRead;

        while (bytesRead < numBytes) {
            numberOfBytesLastRead = in.read(serBytes, bytesRead, numBytes - bytesRead);

            if (numberOfBytesLastRead == -1) {
                // TODO: What should we do if the reconstitution fails?
                // For now, log the event and throw an exception
                if (log.isDebugEnabled()) {
                    log.debug("readObject(): EPR logCorrelationID ["+logCorrelationIDString+"] "    
                            + " ***WARNING*** unexpected end to data:    data read from input stream ["
                            + bytesRead + "]    expected data size [" + numBytes + "]");
                }

                IOException ioe = new IOException("Unable to deserialize the EndpointReference with logCorrelationID ["
                                                  +logCorrelationIDString+"]"
                                                  +"  Cause: Unexpected end to data from input stream"); 

                throw ioe;
            }

            bytesRead += numberOfBytesLastRead;
        }


        if (bytesRead == 0) {
            IOException ioe = new IOException("Unable to deserialize the EndpointReference with logCorrelationID ["
                                              +logCorrelationIDString+"]"
                                              +"  Cause: No data from input stream"); 

            throw ioe;
        }
        in.readUTF(); // read marker

        ByteArrayInputStream bais = new ByteArrayInputStream(serBytes);

        if (log.isDebugEnabled()) {
            String content = new String(serBytes);

            log.debug("readObject(): EPR logCorrelationID ["+logCorrelationIDString+"] "    
                      +"    expected content size ["+numBytes+"]"
                      +"    content size ["+content.length()+"]"
                      +"    EPR buffered content ["+content+"]"); 
        }

        XMLStreamReader xmlReader = null;

        try {
            xmlReader = StAXUtils.createXMLStreamReader(bais);
            StAXOMBuilder builder = new StAXOMBuilder(xmlReader);
            OMElement om = builder.getDocumentElement();

            // expand the OM so we can close the stream reader
            om.build();

            // trace point
            if (log.isDebugEnabled()) {
                log.debug(myClassName + ":readObject():  "  
                          + " EPR ["+logCorrelationIDString + "]"
                          + " EPR OM content ["+om.toString()+ "]");
            }

            EndpointReferenceHelper.fromOM(this, om, AddressingConstants.Final.WSA_NAMESPACE);


        } catch (Exception e) {
            IOException ioe = new IOException("Unable to deserialize the EndpointReference with logCorrelationID ["
                                              +logCorrelationIDString+"]"); 
            ioe.initCause(e);

            if (log.isDebugEnabled()) {
                log.debug("readObject(): Unable to deserialize the EPR with logCorrelationID ["
                          +logCorrelationIDString+"]   original error ["+e.getClass().getName()
                          +"]  message ["+e.getMessage()+"]",e);  
            }

            throw ioe;

        } finally {
        	// Make sure that the reader is properly closed
            // Note that closing a ByteArrayInputStream has no effect

            if (xmlReader != null) {
                try {
                    xmlReader.close();
                } catch (Exception e2) {
                    IOException ioe2 = new IOException("Unable to close the XMLStreamReader for the EndpointReference with logCorrelationID ["
                                                      +logCorrelationIDString+"]"); 
                    ioe2.initCause(e2);

                    if (log.isDebugEnabled()) {
                        log.debug("readObject(): Unable to close the XMLStreamReader for the EPR with logCorrelationID ["
                                  +logCorrelationIDString+"]   original error ["+e2.getClass().getName()
                                  +"]  message ["+e2.getMessage()+"]",e2);  
                    }

                    throw ioe2;
                }
            }
        }
    }

    /**
     * Get the ID associated with this object instance.
     *
     * @return A string that can be output to a log file as an identifier
     *         for this object instance.  It is suitable for matching related log
     *         entries.
     */
    public String getLogCorrelationIDString() {
        if (logCorrelationIDString == null) {
            logCorrelationIDString = myClassName + "@" + UUIDGenerator.getUUID();
        }
        return logCorrelationIDString;
    }

}
