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