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