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