001/*
002 * ============================================================================
003 *  Copyright © 2002-2023 by Thomas Thrien.
004 *  All Rights Reserved.
005 * ============================================================================
006 *  Licensed to the public under the agreements of the GNU Lesser General Public
007 *  License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *       http://www.gnu.org/licenses/lgpl.html
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 *  License for the specific language governing permissions and limitations
015 *  under the License.
016 */
017
018package org.tquadrat.foundation.xml.builder.internal;
019
020import static java.lang.String.format;
021import static org.apiguardian.api.API.Status.INTERNAL;
022import static org.tquadrat.foundation.lang.CommonConstants.EMPTY_STRING;
023import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
024import static org.tquadrat.foundation.xml.builder.spi.SGMLPrinter.repeat;
025
026import java.util.Optional;
027import java.util.function.Function;
028
029import org.apiguardian.api.API;
030import org.tquadrat.foundation.annotation.ClassVersion;
031import org.tquadrat.foundation.xml.builder.spi.Element;
032
033/**
034 *  This class defines the plain text that is the content of an SGML element as
035 *  such an element.
036 *
037 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
038 *  @version $Id: Text.java 1071 2023-09-30 01:49:32Z tquadrat $
039 *  @since 0.0.5
040 *
041 *  @UMLGraph.link
042 */
043@SuppressWarnings( "NewClassNamingConvention" )
044@ClassVersion( sourceVersion = "$Id: Text.java 1071 2023-09-30 01:49:32Z tquadrat $" )
045@API( status = INTERNAL, since = "0.0.5" )
046public class Text implements Element
047{
048        /*------------*\
049    ====** Attributes **=======================================================
050        \*------------*/
051    /**
052     *  The escape function.
053     */
054    private final Function<? super CharSequence, String> m_EscapeFunction;
055
056    /**
057     *  The flag that indicates if this text element is to be treated as a
058     *  block element. This is usually {@code false}, but for predefined
059     *  markup, it can be {@code true}.
060     *
061     *  @see org.tquadrat.foundation.xml.builder.spi.ChildSupport#addPredefinedMarkup(CharSequence)
062     */
063    private final boolean m_IsBlock;
064
065    /**
066     *  The parent element for this comment.
067     */
068    private Element m_Parent;
069
070    /**
071     *  The text.
072     */
073    private final CharSequence m_Text;
074
075        /*--------------*\
076    ====** Constructors **=====================================================
077        \*--------------*/
078    /**
079     *  Creates a new {@code Text} object.
080     *
081     *  @param  text    The text.
082     *  @param  escapeFunction  The function that is used to escape special
083     *      characters in the given text according to the target format.
084     *  @param  isBlock The flag that indicates if this text element is to be
085     *      treated as a block element. This is usually {@code false}, but for
086     *      predefined markup, it can be {@code true}.
087     *
088     *  @see org.tquadrat.foundation.xml.builder.spi.ChildSupport#addPredefinedMarkup(CharSequence)
089     */
090    public Text( final CharSequence text, final Function<? super CharSequence, String> escapeFunction, final boolean isBlock )
091    {
092        requireNonNullArgument( escapeFunction, "escapeFunction" );
093        m_Text = requireNonNullArgument( text, "text" ).toString();
094        m_EscapeFunction = escapeFunction;
095        m_IsBlock = isBlock;
096    }   //  Text()
097
098    /**
099     *  Creates a new {@code Text} object.
100     *
101     *  @param  text    The text.
102     *  @param  escapeFunction  The function that is used to escape special
103     *      characters in the given text according to the target format.
104     */
105    public Text( final CharSequence text, final Function<? super CharSequence, String> escapeFunction )
106    {
107        this( text, escapeFunction, false );
108    }   //  Text()
109
110        /*---------*\
111    ====** Methods **==========================================================
112        \*---------*/
113    /**
114     *  {@inheritDoc}
115     */
116    @Override
117    public final String getElementName() { return "[TEXT]"; }
118
119    /**
120     *  {@inheritDoc}
121     */
122    @Override
123    public final Optional<Element> getParent() { return Optional.ofNullable( m_Parent ); }
124
125    /**
126     *  {@inheritDoc}
127     */
128    @Override
129    public final boolean isBlock() { return m_IsBlock; }
130
131    /**
132     *  {@inheritDoc}
133     */
134    @Override
135    public final <E extends Element> void setParent( final E parent ) { m_Parent = requireNonNullArgument( parent, "parent" ); }
136
137    /**
138     *  {@inheritDoc}
139     */
140    @Override
141    public final String toString( final int indentationLevel, final boolean prettyPrint )
142    {
143        final String retValue;
144        if( m_IsBlock )
145        {
146            //---* Calculate the indentation *---------------------------------
147            /*
148             * If the direct parent is an inline element, the block is false.
149             */
150            final var parent = getParent();
151            final var block = parent.map( element -> element.isBlock() && isBlock() ).orElseGet( this::isBlock );
152            final var filler = (prettyPrint && block) ? "\n" + repeat( indentationLevel ) : EMPTY_STRING;
153
154            //---* Render the text *-------------------------------------------
155            retValue = format( "%2$s%1$s", m_EscapeFunction.apply( m_Text ), filler );
156        }
157        else
158        {
159            retValue = m_EscapeFunction.apply( m_Text );
160        }
161
162        //---* Done *----------------------------------------------------------
163        return retValue;
164    }   //  toString()
165
166    /**
167     *  {@inheritDoc}
168     */
169    @Override
170    public final String toString() { return toString( 0, true ); }
171}
172//  class TextElement
173
174/*
175 *  End of File
176 */