Coverage Report - org.apache.maven.doxia.sink.SinkEventAttributeSet
 
Classes in this File Line Coverage Branch Coverage Complexity
SinkEventAttributeSet
100%
105/105
97%
43/44
2,04
 
 1  
 package org.apache.maven.doxia.sink;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import java.util.Collections;
 23  
 import java.util.Enumeration;
 24  
 import java.util.LinkedHashMap;
 25  
 import java.util.Map;
 26  
 
 27  
 import javax.swing.text.AttributeSet;
 28  
 
 29  
 /**
 30  
  * Implementation of MutableAttributeSet using a LinkedHashMap.
 31  
  *
 32  
  * @author ltheussl
 33  
  * @version $Id: SinkEventAttributeSet.java 1185112 2011-10-17 11:33:00Z ltheussl $
 34  
  * @since 1.1
 35  
  */
 36  
 public class SinkEventAttributeSet
 37  
     implements SinkEventAttributes, Cloneable
 38  
 {
 39  
     /**
 40  
      * An unmodifiable attribute set containing only an underline attribute.
 41  
      */
 42  
     public static final SinkEventAttributes UNDERLINE;
 43  
 
 44  
     /**
 45  
      * An unmodifiable attribute set containing only an overline attribute.
 46  
      */
 47  
     public static final SinkEventAttributes OVERLINE;
 48  
 
 49  
     /**
 50  
      * An unmodifiable attribute set containing only a linethrough attribute.
 51  
      */
 52  
     public static final SinkEventAttributes LINETHROUGH;
 53  
 
 54  
     /**
 55  
      * An unmodifiable attribute set containing only a boxed attribute.
 56  
      */
 57  
     public static final SinkEventAttributes BOXED;
 58  
 
 59  
     /**
 60  
      * An unmodifiable attribute set containing only a bold attribute.
 61  
      */
 62  
     public static final SinkEventAttributes BOLD;
 63  
 
 64  
     /**
 65  
      * An unmodifiable attribute set containing only an italic attribute.
 66  
      */
 67  
     public static final SinkEventAttributes ITALIC;
 68  
 
 69  
     /**
 70  
      * An unmodifiable attribute set containing only a monospaced attribute.
 71  
      */
 72  
     public static final SinkEventAttributes MONOSPACED;
 73  
 
 74  
     /**
 75  
      * An unmodifiable attribute set containing only a left attribute.
 76  
      */
 77  
     public static final SinkEventAttributes LEFT;
 78  
 
 79  
     /**
 80  
      * An unmodifiable attribute set containing only a right attribute.
 81  
      */
 82  
     public static final SinkEventAttributes RIGHT;
 83  
 
 84  
     /**
 85  
      * An unmodifiable attribute set containing only a center attribute.
 86  
      */
 87  
     public static final SinkEventAttributes CENTER;
 88  
 
 89  
     /**
 90  
      * An unmodifiable attribute set containing only a justify attribute.
 91  
      */
 92  
     public static final SinkEventAttributes JUSTIFY;
 93  
 
 94  
 
 95  
     static
 96  
     {
 97  2
         UNDERLINE = new SinkEventAttributeSet( new String[] {DECORATION, "underline"} ).unmodifiable();
 98  2
         OVERLINE = new SinkEventAttributeSet( new String[] {DECORATION, "overline"} ).unmodifiable();
 99  2
         LINETHROUGH = new SinkEventAttributeSet( new String[] {DECORATION, "line-through"} ).unmodifiable();
 100  2
         BOXED = new SinkEventAttributeSet( new String[] {DECORATION, "boxed"} ).unmodifiable();
 101  
 
 102  2
         BOLD = new SinkEventAttributeSet( new String[] {STYLE, "bold"} ).unmodifiable();
 103  2
         ITALIC = new SinkEventAttributeSet( new String[] {STYLE, "italic"} ).unmodifiable();
 104  2
         MONOSPACED = new SinkEventAttributeSet( new String[] {STYLE, "monospaced"} ).unmodifiable();
 105  
 
 106  2
         LEFT = new SinkEventAttributeSet( new String[] {ALIGN, "left"} ).unmodifiable();
 107  2
         RIGHT = new SinkEventAttributeSet( new String[] {ALIGN, "right"} ).unmodifiable();
 108  2
         CENTER = new SinkEventAttributeSet( new String[] {ALIGN, "center"} ).unmodifiable();
 109  2
         JUSTIFY = new SinkEventAttributeSet( new String[] {ALIGN, "justify"} ).unmodifiable();
 110  2
     }
 111  
 
 112  
     private Map<String, Object> attribs;
 113  
 
 114  
     private AttributeSet resolveParent;
 115  
 
 116  
     /**
 117  
      * Constructs a new, empty SinkEventAttributeSet with default size 5.
 118  
      */
 119  
     public SinkEventAttributeSet()
 120  
     {
 121  136
         this( 5 );
 122  136
     }
 123  
 
 124  
     /**
 125  
      * Constructs a new, empty SinkEventAttributeSet with the specified initial size.
 126  
      *
 127  
      * @param size the initial number of attribs.
 128  
      */
 129  
     public SinkEventAttributeSet( int size )
 130  470
     {
 131  470
         attribs = new LinkedHashMap<String, Object>( size );
 132  470
     }
 133  
 
 134  
     /**
 135  
      * Constructs a new SinkEventAttributeSet with the attribute name-value
 136  
      * mappings as given by the specified String array.
 137  
      *
 138  
      * @param attributes the specified String array. If the length of this array
 139  
      * is not an even number, an IllegalArgumentException is thrown.
 140  
      */
 141  
     public SinkEventAttributeSet( String[] attributes )
 142  38
     {
 143  38
         int n = attributes.length;
 144  
 
 145  38
         if ( ( n % 2 ) != 0 )
 146  
         {
 147  2
             throw new IllegalArgumentException( "Missing attribute!" );
 148  
         }
 149  
 
 150  36
         attribs = new LinkedHashMap<String, Object>( n / 2 );
 151  
 
 152  78
         for ( int i = 0; i < n; i += 2 )
 153  
         {
 154  42
             attribs.put( attributes[i], attributes[i + 1] );
 155  
         }
 156  36
     }
 157  
 
 158  
     /**
 159  
      * Constructs a new SinkEventAttributeSet with the same attribute name-value
 160  
      * mappings as in the specified AttributeSet.
 161  
      *
 162  
      * @param attributes the specified AttributeSet.
 163  
      */
 164  
     public SinkEventAttributeSet( AttributeSet attributes )
 165  14
     {
 166  14
         attribs = new LinkedHashMap<String, Object>( attributes.getAttributeCount() );
 167  
 
 168  14
         Enumeration<?> names = attributes.getAttributeNames();
 169  
 
 170  28
         while ( names.hasMoreElements() )
 171  
         {
 172  14
             Object name = names.nextElement();
 173  
 
 174  14
             attribs.put( name.toString(), attributes.getAttribute( name ) );
 175  14
         }
 176  14
     }
 177  
 
 178  
     /**
 179  
      * Replace this AttributeSet by an unmodifiable view of itself.
 180  
      * Any subsequent attempt to add, remove or modify the underlying mapping
 181  
      * will result in an UnsupportedOperationException.
 182  
      *
 183  
      * @return an unmodifiable view of this AttributeSet.
 184  
      *
 185  
      * @since 1.1.1
 186  
      */
 187  
     public SinkEventAttributeSet unmodifiable()
 188  
     {
 189  22
         this.attribs = Collections.unmodifiableMap( attribs );
 190  
 
 191  22
         return this;
 192  
     }
 193  
 
 194  
     /**
 195  
      * Checks whether the set of attribs is empty.
 196  
      *
 197  
      * @return true if the set is empty.
 198  
      */
 199  
     public boolean isEmpty()
 200  
     {
 201  4
         return attribs.isEmpty();
 202  
     }
 203  
 
 204  
     /** {@inheritDoc} */
 205  
     public int getAttributeCount()
 206  
     {
 207  218
         return attribs.size();
 208  
     }
 209  
 
 210  
     /** {@inheritDoc} */
 211  
     public boolean isDefined( Object attrName )
 212  
     {
 213  42
         return attribs.containsKey( attrName );
 214  
     }
 215  
 
 216  
     /** {@inheritDoc} */
 217  
     public boolean isEqual( AttributeSet attr )
 218  
     {
 219  18
         return ( ( getAttributeCount() == attr.getAttributeCount() )
 220  
                 && containsAttributes( attr ) );
 221  
     }
 222  
 
 223  
     /** {@inheritDoc} */
 224  
     public AttributeSet copyAttributes()
 225  
     {
 226  4
         return ( (AttributeSet) clone() );
 227  
     }
 228  
 
 229  
     /** {@inheritDoc} */
 230  
     public Enumeration<String> getAttributeNames()
 231  
     {
 232  530
         return Collections.enumeration( attribs.keySet() );
 233  
     }
 234  
 
 235  
     /** {@inheritDoc} */
 236  
     public Object getAttribute( Object key  )
 237  
     {
 238  454
         Object value = attribs.get( key  );
 239  
 
 240  454
         if ( value == null )
 241  
         {
 242  42
             AttributeSet parent = getResolveParent();
 243  
 
 244  42
             if ( parent != null )
 245  
             {
 246  2
                 value = parent.getAttribute( key  );
 247  
             }
 248  
         }
 249  
 
 250  454
         return value;
 251  
     }
 252  
 
 253  
     /** {@inheritDoc} */
 254  
     public boolean containsAttribute( Object name, Object value )
 255  
     {
 256  26
         return value.equals( getAttribute( name ) );
 257  
     }
 258  
 
 259  
     /** {@inheritDoc} */
 260  
     public boolean containsAttributes( AttributeSet attributes )
 261  
     {
 262  26
         boolean result = true;
 263  
 
 264  26
         Enumeration<?> names = attributes.getAttributeNames();
 265  
 
 266  50
         while ( result && names.hasMoreElements() )
 267  
         {
 268  24
             Object name = names.nextElement();
 269  24
             result = attributes.getAttribute( name ).equals( getAttribute( name ) );
 270  24
         }
 271  
 
 272  26
         return result;
 273  
     }
 274  
 
 275  
     /**
 276  
      * {@inheritDoc}
 277  
      *
 278  
      * Adds an attribute with the given name and value.
 279  
      */
 280  
     public void addAttribute( Object name, Object value )
 281  
     {
 282  326
         attribs.put( name.toString(), value );
 283  326
     }
 284  
 
 285  
     /** {@inheritDoc} */
 286  
     public void addAttributes( AttributeSet attributes  )
 287  
     {
 288  88
         if ( attributes == null || attributes.getAttributeCount() == 0 )
 289  
         {
 290  34
             return;
 291  
         }
 292  
 
 293  54
         Enumeration<?> names = attributes.getAttributeNames();
 294  
 
 295  110
         while ( names.hasMoreElements() )
 296  
         {
 297  56
             Object name = names.nextElement();
 298  
 
 299  56
             addAttribute( name, attributes.getAttribute( name ) );
 300  56
         }
 301  54
     }
 302  
 
 303  
     /** {@inheritDoc} */
 304  
     public void removeAttribute( Object name )
 305  
     {
 306  58
         attribs.remove( name );
 307  58
     }
 308  
 
 309  
     /** {@inheritDoc} */
 310  
     public void removeAttributes( Enumeration<?> names )
 311  
     {
 312  4
         while ( names.hasMoreElements() )
 313  
         {
 314  2
             removeAttribute( names.nextElement() );
 315  
         }
 316  2
     }
 317  
 
 318  
     /** {@inheritDoc} */
 319  
     public void removeAttributes( AttributeSet attributes  )
 320  
     {
 321  20
         if ( attributes == null )
 322  
         {
 323  2
             return;
 324  
         }
 325  18
         else if ( attributes == this )
 326  
         {
 327  12
             attribs.clear();
 328  
         }
 329  
         else
 330  
         {
 331  6
             Enumeration<?> names = attributes.getAttributeNames();
 332  
 
 333  12
             while ( names.hasMoreElements() )
 334  
             {
 335  6
                 Object name = names.nextElement();
 336  6
                 Object value = attributes.getAttribute( name );
 337  
 
 338  6
                 if ( value.equals( getAttribute( name ) ) )
 339  
                 {
 340  4
                     removeAttribute( name );
 341  
                 }
 342  6
             }
 343  
         }
 344  18
     }
 345  
 
 346  
     /** {@inheritDoc} */
 347  
     public AttributeSet getResolveParent()
 348  
     {
 349  46
         return this.resolveParent;
 350  
     }
 351  
 
 352  
     /** {@inheritDoc} */
 353  
     public void setResolveParent( AttributeSet parent )
 354  
     {
 355  10
         this.resolveParent = parent;
 356  10
     }
 357  
 
 358  
     /** {@inheritDoc} */
 359  
     @Override
 360  
     public Object clone()
 361  
     {
 362  10
         SinkEventAttributeSet attr = new SinkEventAttributeSet( attribs.size() );
 363  10
         attr.attribs = new LinkedHashMap<String, Object>( attribs );
 364  
 
 365  10
         if ( resolveParent != null )
 366  
         {
 367  2
             attr.resolveParent = resolveParent.copyAttributes();
 368  
         }
 369  
 
 370  10
         return attr;
 371  
     }
 372  
 
 373  
     /** {@inheritDoc} */
 374  
     @Override
 375  
     public int hashCode()
 376  
     {
 377  8
         final int parentHash = ( resolveParent == null ? 0 : resolveParent.hashCode() );
 378  
 
 379  8
         return attribs.hashCode() + parentHash;
 380  
     }
 381  
 
 382  
     /** {@inheritDoc} */
 383  
     @Override
 384  
     public boolean equals( Object obj )
 385  
     {
 386  16
         if ( this == obj )
 387  
         {
 388  2
             return true;
 389  
         }
 390  
 
 391  14
         if ( obj instanceof SinkEventAttributeSet )
 392  
         {
 393  12
             return isEqual( (SinkEventAttributeSet) obj  );
 394  
         }
 395  
 
 396  2
         return false;
 397  
     }
 398  
 
 399  
     /** {@inheritDoc} */
 400  
     @Override
 401  
     public String toString()
 402  
     {
 403  6
         StringBuilder s = new StringBuilder();
 404  6
         Enumeration<String> names = getAttributeNames();
 405  
 
 406  12
         while ( names.hasMoreElements() )
 407  
         {
 408  6
             String key = names.nextElement();
 409  6
             String value = getAttribute( key ).toString();
 410  
 
 411  6
             s.append( ' ' ).append( key ).append( '=' ).append( value );
 412  6
         }
 413  
 
 414  6
         return s.toString();
 415  
     }
 416  
 
 417  
 }