/*
 * 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_LAYOUT_H
#define _LOG4CXX_LAYOUT_H

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


#include <log4cxx/helpers/objectimpl.h>
#include <log4cxx/helpers/objectptr.h>
#include <log4cxx/spi/optionhandler.h>
#include <log4cxx/spi/loggingevent.h>


namespace log4cxx
{
/**
Extend this abstract class to create your own log layout format.
*/
class LOG4CXX_EXPORT Layout :
    public virtual spi::OptionHandler,
    public virtual helpers::ObjectImpl
{
    public:
        DECLARE_ABSTRACT_LOG4CXX_OBJECT(Layout)
        BEGIN_LOG4CXX_CAST_MAP()
        LOG4CXX_CAST_ENTRY(Layout)
        LOG4CXX_CAST_ENTRY(spi::OptionHandler)
        END_LOG4CXX_CAST_MAP()

        virtual ~Layout();
        void addRef() const;
        void releaseRef() const;


        /**
        Implement this method to create your own layout format.
        */
        virtual void format(LogString& output,
                            const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool) const = 0;

        /**
        Returns the content type output by this layout. The base class
        returns "text/plain".
        */
        virtual LogString getContentType() const;

        /**
        Append the header for the layout format. The base class does
        nothing.
        */
        virtual void appendHeader(LogString& output, log4cxx::helpers::Pool& p);

        /**
        Append the footer for the layout format. The base class does
        nothing.
        */
        virtual void appendFooter(LogString& output, log4cxx::helpers::Pool& p);

        /**
        If the layout handles the throwable object contained within
        {@link spi::LoggingEvent LoggingEvent}, then the layout should return
        <code>false</code>. Otherwise, if the layout ignores throwable
        object, then the layout should return <code>true</code>.

        <p>The SimpleLayout, TTCCLayout,
        PatternLayout all return <code>true</code>. The {@link
        xml::XMLLayout XMLLayout} returns <code>false</code>.
        */
        virtual bool ignoresThrowable() const = 0;
};
LOG4CXX_PTR_DEF(Layout);
}

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

#endif // _LOG4CXX_LAYOUT_H
