001/*
002 * ============================================================================
003 * Copyright © 2002-2025 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.svg.internal;
019
020import static java.lang.String.join;
021import static java.util.Collections.emptyList;
022import static java.util.stream.Collectors.joining;
023import static org.apiguardian.api.API.Status.INTERNAL;
024import static org.tquadrat.foundation.lang.CommonConstants.EMPTY_STRING;
025import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
026import static org.tquadrat.foundation.svg.SVGUtils.SVGELEMENT_Style;
027import static org.tquadrat.foundation.util.StringUtils.isNotEmptyOrBlank;
028import static org.tquadrat.foundation.util.StringUtils.stream;
029import static org.tquadrat.foundation.xml.builder.XMLBuilderUtils.createXMLElement;
030import static org.tquadrat.foundation.xml.builder.XMLElement.Flags.VALIDATES_ATTRIBUTES;
031import static org.tquadrat.foundation.xml.builder.spi.SGMLPrinter.repeat;
032
033import java.util.ArrayList;
034import java.util.Collection;
035import java.util.List;
036
037import org.apiguardian.api.API;
038import org.tquadrat.foundation.annotation.ClassVersion;
039import org.tquadrat.foundation.svg.SVGStyle;
040import org.tquadrat.foundation.xml.builder.XMLElement;
041import org.tquadrat.foundation.xml.builder.spi.Element;
042
043/**
044 *  The implementation of the interface
045 *  {@link SVGStyle}
046 *  for the SVG {@code <style>} element.
047 *
048 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
049 *  @version $Id: SVGStyleImpl.java 1151 2025-10-01 21:32:15Z tquadrat $
050 *  @since 0.0.5
051 *
052 *  @UMLGraph.link
053 */
054@ClassVersion( sourceVersion = "$Id: SVGStyleImpl.java 1151 2025-10-01 21:32:15Z tquadrat $" )
055@API( status = INTERNAL, since = "0.0.5" )
056public final class SVGStyleImpl extends SVGElementImpl implements SVGStyle
057{
058        /*------------*\
059    ====** Attributes **=======================================================
060        \*------------*/
061    /**
062     *  The lines of the CSS style definitions.
063     */
064    private final List<String> m_StyleDefinitions = new ArrayList<>();
065
066        /*--------------*\
067    ====** Constructors **=====================================================
068        \*--------------*/
069    /**
070     *  Creates a new {@code SVGStyleImpl} instance.
071     */
072    public SVGStyleImpl()
073    {
074        super( SVGELEMENT_Style, VALIDATES_ATTRIBUTES );
075
076        //---* The attributes for the <style> element *------------------------
077        updateRegistries( emptyList(), CORE_ATTRIBUTES );
078    }   //  SVGStyleImpl()
079
080    /**
081     *  Creates a new {@code SVGStyleImpl} instance.
082     *
083     *  @param  styles  The style definitions to add.
084     */
085    public SVGStyleImpl( final CharSequence... styles )
086    {
087        this();
088        addStyle( styles );
089    }   //  SVGStyleImpl()
090
091        /*---------*\
092    ====** Methods **==========================================================
093        \*---------*/
094    /**
095     *  {@inheritDoc}
096     */
097    @Override
098    public final void addStyle( final CharSequence... styles )
099    {
100        for( final var style : requireNonNullArgument( styles, "styles" ) )
101        {
102            if( isNotEmptyOrBlank( style ) )
103            {
104                stream( style, '\n' ).forEach( m_StyleDefinitions::add );
105            }
106            else
107            {
108                m_StyleDefinitions.add( EMPTY_STRING );
109            }
110        }
111    }   //  addStyle()
112
113    /**
114     *  {@inheritDoc}
115     */
116    @Override
117    public final Collection<? extends Element> getChildren()
118    {
119        final Collection<? extends Element> retValue;
120        if( m_StyleDefinitions.isEmpty() )
121        {
122            retValue = super.getChildren();
123        }
124        else
125        {
126            final var styleSheet = join( "\n", m_StyleDefinitions );
127
128            final var element = createXMLElement( getElementName() );
129            for( final var child : super.getChildren() ) element.addChild( (XMLElement) child );
130            element.addCDATA( styleSheet );
131
132            retValue = element.getChildren();
133        }
134
135        //---* Done *----------------------------------------------------------
136        return retValue;
137    }   //  getChildren()
138
139    /**
140     *  {@inheritDoc}
141     */
142    @Override
143    public final String getStyleSheet()
144    {
145        final var retValue = join( "\n", m_StyleDefinitions );
146
147        //---* Done *----------------------------------------------------------
148        return retValue;
149    }   //  getStyleSheet()
150
151    /**
152     *  {@inheritDoc}
153     */
154    @Override
155    public final boolean hasChildren() { return !m_StyleDefinitions.isEmpty() || super.hasChildren(); }
156
157    /**
158     *  {@inheritDoc}
159     */
160    @Override
161    public final void merge( final SVGStyle other )
162    {
163        if( requireNonNullArgument( other, "other" ) instanceof final SVGStyleImpl styleImpl )
164        {
165            m_StyleDefinitions.addAll( styleImpl.m_StyleDefinitions );
166        }
167        else
168        {
169            addStyle( other.getStyleSheet() );
170        }
171    }   //  merge()
172
173    /**
174     *  {@inheritDoc}
175     */
176    @Override
177    public final String toString( final int indentationLevel, final boolean prettyPrint )
178    {
179        final String retValue;
180        if( m_StyleDefinitions.isEmpty() )
181        {
182            retValue = super.toString( indentationLevel, prettyPrint );
183        }
184        else
185        {
186            final var indentation = prettyPrint ? "\n" + repeat( indentationLevel + 1 ) : "\n";
187            final var styleSheet = m_StyleDefinitions.stream().collect( joining( indentation, indentation, indentation ) );
188
189            final var element = createXMLElement( getElementName() );
190            for( final var child : super.getChildren() ) element.addChild( (XMLElement) child );
191            for( final var attribute : getAttributes().entrySet() ) element.setAttribute( attribute.getKey(), attribute.getValue() );
192            element.addCDATA( styleSheet );
193
194            retValue = element.toString( indentationLevel, prettyPrint );
195        }
196
197        //---* Done *----------------------------------------------------------
198        return retValue;
199    }   //  toString()
200}
201//  class SVGStyleImpl
202
203/*
204 *  End of File
205 */