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

#ifndef _LOG4CXX_NDC_H
#define _LOG4CXX_NDC_H

#if defined(_MSC_VER)
#pragma warning ( push )
#pragma warning ( disable: 4231 4251 4275 4786 )
#endif

#include <log4cxx/log4cxx.h>
#include <log4cxx/logstring.h>
#include <stack>

namespace log4cxx
{
        /**
        the ndc class implements <i>nested diagnostic contexts</i> as
        defined by neil harrison in the article "patterns for logging
        diagnostic messages" part of the book "<i>pattern languages of
        program design 3</i>" edited by martin et al.

        <p>a nested diagnostic context, or ndc in short, is an instrument
        to distinguish interleaved log output from different sources. log
        output is typically interleaved when a server handles multiple
        clients near-simultaneously.

        <p>interleaved log output can still be meaningful if each log entry
        from different contexts had a distinctive stamp. this is where ndcs
        come into play.

        <p><em><b>note that ndcs are managed on a per thread
        basis</b></em>. ndc operations such as #push,
        #pop, #clear and #getDepth
        affect the ndc of the <em>current</em> thread only. ndcs of other
        threads remain unaffected.

        <p>for example, a servlet can build a per client request ndc
        consisting the clients host name and other information contained in
        the the request. <em>cookies</em> are another source of distinctive
        information. to build an ndc one uses the #push
        operation. simply put,

        <p><ul>
         <li>contexts can be nested.

         <p><li>when entering a context, call <code>ndc.push</code>. as a
         side effect, if there is no nested diagnostic context for the
         current thread, this method will create it.

         <p><li>when leaving a context, call <code>ndc.pop</code>.

         <p><li><b>when exiting a thread make sure to call #remove
         </b>.
        </ul>

        <p>there is no penalty for forgetting to match each
        <code>push</code> operation with a corresponding <code>pop</code>,
        except the obvious mismatch between the real application context
        and the context set in the ndc.

        <p>if configured to do so, PatternLayout and
        TTCCLayout instances automatically retrieve the nested diagnostic
        context for the current thread without any user intervention.
        hence, even if a servlet is serving multiple clients
        simultaneously, the logs emanating from the same code (belonging to
        the same logger) can still be distinguished because each client
        request will have a different ndc tag.

        <p>heavy duty systems should call the #remove method when
        leaving the run method of a thread. this ensures that the memory
        used by the thread can be freed by the java garbage
        collector. there is a mechanism to lazily remove references to dead
        threads. in practice, this means that you can be a little sloppy
        and sometimes forget to call #remove before exiting a
        thread.

        */
        class LOG4CXX_EXPORT NDC
        {
        public:
                /**
                 *  Pair of Message and FullMessage.
                 */
                typedef std::pair<LogString, LogString> DiagnosticContext;
                typedef std::stack<DiagnosticContext> Stack;

                /**
                 Creates a nested diagnostic context.
                 Since java performs no automatic cleanup of objects when a
                 scope is left, in log4j push() and pop() must be used
                 to manage the NDC. For convenience, log4cxx provides
                 an NDC constructor and destructor which simply call the push() and
                 pop() methods, allowing for automatic cleanup when the current
                 scope ends.

                 @param message The new diagnostic context information.
                 @see The #push method.
                 */
                NDC(const std::string& message);

                /**
                Removes the topmost element from the NDC stack.

                @see The #pop method.
                */
                ~NDC();

                /**
                Clear any nested diagnostic information if any. This method is
                useful in cases where the same thread can be potentially used
                over and over in different unrelated contexts.
                */
                static void clear();

                /**
                    Clone the diagnostic context for the current thread.
                    <p>Internally a diagnostic context is represented as a stack.  A
                    given thread can supply the stack (i.e. diagnostic context) to a
                    child thread so that the child can inherit the parent thread's
                    diagnostic context.
                    <p>The child thread uses the #inherit method to
                    inherit the parent's diagnostic context.
                    <p>If not passed to #inherit, returned stack should be deleted by caller.
                    @return Stack A clone of the current thread's diagnostic context, will not be null.
                */
                static Stack * cloneStack();

                /**
                Inherit the diagnostic context of another thread.
                <p>The parent thread can obtain a reference to its diagnostic
                context using the #cloneStack method.  It should
                communicate this information to its child so that it may inherit
                the parent's diagnostic context.
                <p>The parent's diagnostic context is cloned before being
                inherited. In other words, once inherited, the two diagnostic
                contexts can be managed independently.
                @param stack The diagnostic context of the parent thread,
                    will be deleted during call.  If NULL, NDC will not be modified.
                */
                static void inherit(Stack * stack);

                /**
                 *   Get the current value of the NDC of the
                 *   currrent thread.
                * @param dest destination to which to append content of NDC.
                * @return true if NDC is set.
                */
                static bool get(LogString& dest);

                /**
                Get the current nesting depth of this diagnostic context.
                */
                static int getDepth();


                /**
                * Tests if the NDC is empty.
                */
                static bool empty();

                /**
                Pop top value off stack.
                @return top value.
                */
                static LogString pop();
                /**
                Pop top value off stack.
                @param buf to which top value is appended.
                @return true if NDC contained at least one value.
                */
                static bool pop(std::string& buf);

                /**
                Looks at the last diagnostic context at the top of this NDC
                without removing it.
                <p>The returned value is the value that was pushed last. If no
                context is available, then the empty string "" is returned.
                @return String The innermost diagnostic context.
                */
                static LogString peek();
                /**
                Get top value without removing value.
                @param buf to which top value is appended.
                @return true if NDC contained at least one value.
                */
                static bool peek(std::string& buf);

                /**
                Push new diagnostic context information for the current thread.
                <p>The contents of the <code>message</code> parameter is
                determined solely by the client.
                @param message The new diagnostic context information.
                */
                static void push(const std::string& message);
                /**
                Push new diagnostic context information for the current thread.
                <p>The contents of the <code>message</code> parameter is
                determined solely by the client.
                @param message The new diagnostic context information.
                */
                static void pushLS(const LogString& message);

                /**
                Remove the diagnostic context for this thread.
                <p>Each thread that created a diagnostic context by calling
                #push should call this method before exiting. Otherwise,
                the memory used by the <b>thread</b> cannot be reclaimed by the
                VM.
                <p>As this is such an important problem in heavy duty systems and
                because it is difficult to always guarantee that the remove
                method is called before exiting a thread, this method has been
                augmented to lazily remove references to dead threads. In
                practice, this means that you can be a little sloppy and
                occasionally forget to call #remove before exiting a
                thread. However, you must call <code>remove</code> sometime. If
                you never call it, then your application is sure to run out of
                memory.
                */
                static void remove();

#if LOG4CXX_WCHAR_T_API
               /**
                 Creates a nested diagnostic context.
                 Since java performs no automatic cleanup of objects when a
                 scope is left, in log4j push() and pop() must be used
                 to manage the NDC. For convenience, log4cxx provides
                 an NDC constructor and destructor which simply call the push() and
                 pop() methods, allowing for automatic cleanup when the current
                 scope ends.

                 @param message The new diagnostic context information.
                 @see The #push method.
                 */
                 NDC(const std::wstring& message);
                 /**
                Push new diagnostic context information for the current thread.
                <p>The contents of the <code>message</code> parameter is
                determined solely by the client.
                @param message The new diagnostic context information.
                */
               static void push(const std::wstring& message);
                /**
                 *   Appends the current NDC content to the provided string.
                 *   @param dst destination.
                 *   @return true if NDC value set.
                 */
                static bool peek(std::wstring& dst);
                /**
                 *   Appends the current NDC content to the provided string and removes the value from the NDC.
                 *   @param dst destination.
                 *   @return true if NDC value set.
                 */
                static bool pop(std::wstring& dst);
#endif
#if LOG4CXX_UNICHAR_API
               /**
                 Creates a nested diagnostic context.
                 Since java performs no automatic cleanup of objects when a
                 scope is left, in log4j push() and pop() must be used
                 to manage the NDC. For convenience, log4cxx provides
                 an NDC constructor and destructor which simply call the push() and
                 pop() methods, allowing for automatic cleanup when the current
                 scope ends.

                 @param message The new diagnostic context information.
                 @see The #push method.
                 */
                 NDC(const std::basic_string<UniChar>& message);
                /**
                Push new diagnostic context information for the current thread.
                <p>The contents of the <code>message</code> parameter is
                determined solely by the client.
                @param message The new diagnostic context information.
                */
                static void push(const std::basic_string<UniChar>& message);
                /**
                 *   Appends the current NDC content to the provided string.
                 *   @param dst destination.
                 *   @return true if NDC value set.
                 */
                static bool peek(std::basic_string<UniChar>& dst);
                /**
                 *   Appends the current NDC content to the provided string and removes the value from the NDC.
                 *   @param dst destination.
                 *   @return true if NDC value set.
                 */
                static bool pop(std::basic_string<UniChar>& dst);
#endif
#if LOG4CXX_CFSTRING_API
               /**
                 Creates a nested diagnostic context.
                 Since java performs no automatic cleanup of objects when a
                 scope is left, in log4j push() and pop() must be used
                 to manage the NDC. For convenience, log4cxx provides
                 an NDC constructor and destructor which simply call the push() and
                 pop() methods, allowing for automatic cleanup when the current
                 scope ends.

                 @param message The new diagnostic context information.
                 @see The #push method.
                 */
                 NDC(const CFStringRef& message);
                /**
                Push new diagnostic context information for the current thread.
                <p>The contents of the <code>message</code> parameter is
                determined solely by the client.
                @param message The new diagnostic context information.
                */
                static void push(const CFStringRef& message);
                /**
                 *   Gets the current NDC value.
                 *   @param dst destination.
                 *   @return true if NDC value set.
                 */
                static bool peek(CFStringRef& dst);
                /**
                 *  Gets and removes the current NDC value.
                 *   @param dst destination.
                 *   @return true if NDC value set.
                 */
                static bool pop(CFStringRef& dst);
#endif

        private:
                NDC(const NDC&);
                NDC& operator=(const NDC&);
                static LogString& getMessage(DiagnosticContext& ctx);
                static LogString& getFullMessage(DiagnosticContext& ctx);
        }; // class NDC;
}  // namespace log4cxx

#if defined(_MSC_VER)
#pragma warning (pop)
#endif


#endif // _LOG4CXX_NDC_H
