Author: ltheussl Date: Sat Mar 28 20:54:39 2009 New Revision: 759584 URL: http://svn.apache.org/viewvc?rev=759584&view=rev Log: Fix some problems in SinkEventAttributeSet: o make it Cloneable o add a method to make it unmodifiable o make all static fields unmodifiable o add attribute values as Objects, not Strings o fix potential NPEs in clone() and hashCode()
Added: maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkEventAttributeSetTest.java (with props) Modified: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkEventAttributeSet.java Modified: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkEventAttributeSet.java URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkEventAttributeSet.java?rev=759584&r1=759583&r2=759584&view=diff ============================================================================== --- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkEventAttributeSet.java (original) +++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/SinkEventAttributeSet.java Sat Mar 28 20:54:39 2009 @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashMap; +import java.util.Map; import javax.swing.text.AttributeSet; @@ -33,82 +34,82 @@ * @since 1.1 */ public class SinkEventAttributeSet - implements SinkEventAttributes + implements SinkEventAttributes, Cloneable { /** - * An attribute set containing only an underline attribute. + * An unmodifiable attribute set containing only an underline attribute. */ public static final SinkEventAttributes UNDERLINE; /** - * An attribute set containing only an overline attribute. + * An unmodifiable attribute set containing only an overline attribute. */ public static final SinkEventAttributes OVERLINE; /** - * An attribute set containing only a linethrough attribute. + * An unmodifiable attribute set containing only a linethrough attribute. */ public static final SinkEventAttributes LINETHROUGH; /** - * An attribute set containing only a boxed attribute. + * An unmodifiable attribute set containing only a boxed attribute. */ public static final SinkEventAttributes BOXED; /** - * An attribute set containing only a bold attribute. + * An unmodifiable attribute set containing only a bold attribute. */ public static final SinkEventAttributes BOLD; /** - * An attribute set containing only an italic attribute. + * An unmodifiable attribute set containing only an italic attribute. */ public static final SinkEventAttributes ITALIC; /** - * An attribute set containing only a monospaced attribute. + * An unmodifiable attribute set containing only a monospaced attribute. */ public static final SinkEventAttributes MONOSPACED; /** - * An attribute set containing only a left attribute. + * An unmodifiable attribute set containing only a left attribute. */ public static final SinkEventAttributes LEFT; /** - * An attribute set containing only a right attribute. + * An unmodifiable attribute set containing only a right attribute. */ public static final SinkEventAttributes RIGHT; /** - * An attribute set containing only a center attribute. + * An unmodifiable attribute set containing only a center attribute. */ public static final SinkEventAttributes CENTER; /** - * An attribute set containing only a justify attribute. + * An unmodifiable attribute set containing only a justify attribute. */ public static final SinkEventAttributes JUSTIFY; static { - UNDERLINE = new SinkEventAttributeSet( new String[] {DECORATION, "underline"} ); - OVERLINE = new SinkEventAttributeSet( new String[] {DECORATION, "overline"} ); - LINETHROUGH = new SinkEventAttributeSet( new String[] {DECORATION, "line-through"} ); - BOXED = new SinkEventAttributeSet( new String[] {DECORATION, "boxed"} ); - - BOLD = new SinkEventAttributeSet( new String[] {STYLE, "bold"} ); - ITALIC = new SinkEventAttributeSet( new String[] {STYLE, "italic"} ); - MONOSPACED = new SinkEventAttributeSet( new String[] {STYLE, "monospaced"} ); - - LEFT = new SinkEventAttributeSet( new String[] {ALIGN, "left"} ); - RIGHT = new SinkEventAttributeSet( new String[] {ALIGN, "right"} ); - CENTER = new SinkEventAttributeSet( new String[] {ALIGN, "center"} ); - JUSTIFY = new SinkEventAttributeSet( new String[] {ALIGN, "justify"} ); + UNDERLINE = new SinkEventAttributeSet( new String[] {DECORATION, "underline"} ).unmodifiable(); + OVERLINE = new SinkEventAttributeSet( new String[] {DECORATION, "overline"} ).unmodifiable(); + LINETHROUGH = new SinkEventAttributeSet( new String[] {DECORATION, "line-through"} ).unmodifiable(); + BOXED = new SinkEventAttributeSet( new String[] {DECORATION, "boxed"} ).unmodifiable(); + + BOLD = new SinkEventAttributeSet( new String[] {STYLE, "bold"} ).unmodifiable(); + ITALIC = new SinkEventAttributeSet( new String[] {STYLE, "italic"} ).unmodifiable(); + MONOSPACED = new SinkEventAttributeSet( new String[] {STYLE, "monospaced"} ).unmodifiable(); + + LEFT = new SinkEventAttributeSet( new String[] {ALIGN, "left"} ).unmodifiable(); + RIGHT = new SinkEventAttributeSet( new String[] {ALIGN, "right"} ).unmodifiable(); + CENTER = new SinkEventAttributeSet( new String[] {ALIGN, "center"} ).unmodifiable(); + JUSTIFY = new SinkEventAttributeSet( new String[] {ALIGN, "justify"} ).unmodifiable(); } - private LinkedHashMap attribs; + private Map attribs; private AttributeSet resolveParent; @@ -175,6 +176,20 @@ } /** + * Replace this AttributeSet by an unmodifiable view of itself. + * Any subsequent attempt to add, remove or modify the underlying mapping + * will result in an UnsupportedOperationException. + * + * @return an unmodifiable view of this AttributeSet. + */ + public SinkEventAttributeSet unmodifiable() + { + this.attribs = Collections.unmodifiableMap( attribs ); + + return this; + } + + /** * Checks whether the set of attribs is empty. * * @return true if the set is empty. @@ -262,7 +277,7 @@ */ public void addAttribute( Object name, Object value ) { - attribs.put( name.toString(), value.toString() ); + attribs.put( name.toString(), value ); } /** {...@inheritdoc} */ @@ -341,18 +356,13 @@ /** {...@inheritdoc} */ public Object clone() { - SinkEventAttributeSet attr; + SinkEventAttributeSet attr = new SinkEventAttributeSet( attribs.size() ); + attr.attribs = new LinkedHashMap( attribs ); - try + if ( resolveParent != null ) { - attr = (SinkEventAttributeSet) super.clone(); - attr.attribs = (LinkedHashMap) attribs.clone(); attr.resolveParent = resolveParent.copyAttributes(); } - catch ( CloneNotSupportedException e ) - { - attr = null; - } return attr; } @@ -360,7 +370,9 @@ /** {...@inheritdoc} */ public int hashCode() { - return attribs.hashCode() + resolveParent.hashCode(); + final int parentHash = ( resolveParent == null ? 0 : resolveParent.hashCode() ); + + return attribs.hashCode() + parentHash; } /** {...@inheritdoc} */ Added: maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkEventAttributeSetTest.java URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkEventAttributeSetTest.java?rev=759584&view=auto ============================================================================== --- maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkEventAttributeSetTest.java (added) +++ maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkEventAttributeSetTest.java Sat Mar 28 20:54:39 2009 @@ -0,0 +1,281 @@ +package org.apache.maven.doxia.sink; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.Enumeration; + +import javax.swing.text.AttributeSet; + +import junit.framework.TestCase; + +/** + * Test SinkEventAttributeSet. + * + * @author ltheussl + */ +public class SinkEventAttributeSetTest extends TestCase +{ + + private SinkEventAttributeSet sinkEventAttributeSet; + + /** + * @throws java.lang.Exception if any. + */ + protected void setUp() + throws Exception + { + super.setUp(); + this.sinkEventAttributeSet = new SinkEventAttributeSet(); + } + + /** + * Test of constructors, of class SinkEventAttributeSet. + */ + public void testConstructor() + { + try + { + SinkEventAttributeSet aset = new SinkEventAttributeSet( new String[] {"key"} ); + fail( "missing attribute value!" ); + } + catch ( IllegalArgumentException e ) + { + assertNotNull( e ); + } + } + + /** + * Test of isEmpty method, of class SinkEventAttributeSet. + */ + public void testIsEmpty() + { + assertTrue( sinkEventAttributeSet.isEmpty() ); + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.BOLD ); + assertFalse( sinkEventAttributeSet.isEmpty() ); + } + + /** + * Test of getAttributeCount method, of class SinkEventAttributeSet. + */ + public void testGetAttributeCount() + { + assertEquals( 0, sinkEventAttributeSet.getAttributeCount() ); + sinkEventAttributeSet.addAttribute( "name1", "value1" ); + assertEquals( 1, sinkEventAttributeSet.getAttributeCount() ); + sinkEventAttributeSet.removeAttribute( "name2" ); + assertEquals( 1, sinkEventAttributeSet.getAttributeCount() ); + sinkEventAttributeSet.removeAttribute( "name1" ); + assertEquals( 0, sinkEventAttributeSet.getAttributeCount() ); + + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.BOLD ); + assertEquals( 1, sinkEventAttributeSet.getAttributeCount() ); + sinkEventAttributeSet.removeAttributes( SinkEventAttributeSet.BOXED ); + assertEquals( 1, sinkEventAttributeSet.getAttributeCount() ); + sinkEventAttributeSet.removeAttributes( SinkEventAttributeSet.BOLD ); + assertEquals( 0, sinkEventAttributeSet.getAttributeCount() ); + } + + /** + * Test of isDefined method, of class SinkEventAttributeSet. + */ + public void testIsDefined() + { + assertFalse( sinkEventAttributeSet.isDefined( SinkEventAttributes.DECORATION ) ); + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.BOXED ); + assertTrue( sinkEventAttributeSet.isDefined( SinkEventAttributes.DECORATION ) ); + } + + /** + * Test of isEqual method, of class SinkEventAttributeSet. + */ + public void testIsEqual() + { + SinkEventAttributes instance = new SinkEventAttributeSet( SinkEventAttributeSet.BOLD ); + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.BOLD ); + assertTrue( instance.isEqual( sinkEventAttributeSet ) ); + instance.addAttributes( SinkEventAttributeSet.BOXED ); + assertFalse( instance.isEqual( sinkEventAttributeSet ) ); + } + + /** + * Test of equals method, of class SinkEventAttributeSet. + */ + public void testEquals() + { + assertFalse( sinkEventAttributeSet.equals( null ) ); + assertTrue( sinkEventAttributeSet.equals( sinkEventAttributeSet ) ); + + SinkEventAttributes instance = new SinkEventAttributeSet( SinkEventAttributeSet.BOLD ); + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.BOLD ); + assertTrue( instance.equals( sinkEventAttributeSet ) ); + instance.addAttributes( SinkEventAttributeSet.BOXED ); + assertFalse( instance.equals( sinkEventAttributeSet ) ); + } + + /** + * Test of copyAttributes method, of class SinkEventAttributeSet. + */ + public void testCopyAttributes() + { + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.ITALIC ); + AttributeSet instance = sinkEventAttributeSet.copyAttributes(); + assertTrue( instance.isEqual( sinkEventAttributeSet ) ); + } + + /** + * Test of getAttributeNames method, of class SinkEventAttributeSet. + */ + public void testGetAttributeNames() + { + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.UNDERLINE ); + Enumeration result = sinkEventAttributeSet.getAttributeNames(); + assertEquals( "decoration", result.nextElement() ); + assertFalse( result.hasMoreElements() ); + } + + /** + * Test of getAttribute method, of class SinkEventAttributeSet. + */ + public void testGetAttribute() + { + sinkEventAttributeSet.addAttribute( "key", "value" ); + assertTrue( sinkEventAttributeSet.getAttribute( "key" ).equals( "value" ) ); + assertNull( sinkEventAttributeSet.getAttribute( "bla" ) ); + } + + /** + * Test of containsAttribute method, of class SinkEventAttributeSet. + */ + public void testContainsAttribute() + { + sinkEventAttributeSet.addAttribute( "key", "value" ); + assertTrue( sinkEventAttributeSet.containsAttribute( "key", "value" ) ); + assertFalse( sinkEventAttributeSet.containsAttribute( "key", "valu" ) ); + } + + /** + * Test of containsAttributes method, of class SinkEventAttributeSet. + */ + public void testContainsAttributes() + { + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.JUSTIFY ); + assertTrue( sinkEventAttributeSet.containsAttributes( SinkEventAttributeSet.JUSTIFY ) ); + assertFalse( sinkEventAttributeSet.containsAttributes( SinkEventAttributeSet.BOXED ) ); + } + + /** + * Test of addAttribute method, of class SinkEventAttributeSet. + */ + public void testAddAttribute() + { + assertFalse( sinkEventAttributeSet.containsAttribute( "key", "value" ) ); + sinkEventAttributeSet.addAttribute( "key", "value" ); + assertTrue( sinkEventAttributeSet.containsAttribute( "key", "value" ) ); + sinkEventAttributeSet.removeAttribute( "key" ); + assertFalse( sinkEventAttributeSet.containsAttribute( "key", "value" ) ); + } + + /** + * Test of add/removeAttributes methods, of class SinkEventAttributeSet. + */ + public void testAddAttributes() + { + assertFalse( sinkEventAttributeSet.containsAttributes( SinkEventAttributeSet.JUSTIFY ) ); + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.JUSTIFY ); + assertTrue( sinkEventAttributeSet.containsAttributes( SinkEventAttributeSet.JUSTIFY ) ); + + sinkEventAttributeSet.removeAttributes( SinkEventAttributeSet.JUSTIFY ); + assertFalse( sinkEventAttributeSet.containsAttributes( SinkEventAttributeSet.JUSTIFY ) ); + + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.JUSTIFY ); + sinkEventAttributeSet.removeAttributes( SinkEventAttributeSet.JUSTIFY.getAttributeNames() ); + assertFalse( sinkEventAttributeSet.containsAttributes( SinkEventAttributeSet.JUSTIFY ) ); + + sinkEventAttributeSet.setResolveParent( SinkEventAttributeSet.JUSTIFY ); + assertTrue( sinkEventAttributeSet.containsAttributes( SinkEventAttributeSet.JUSTIFY ) ); + + sinkEventAttributeSet.removeAttributes( (AttributeSet) null ); // should do nothing + } + + /** + * Test of getResolveParent method, of class SinkEventAttributeSet. + */ + public void testGetResolveParent() + { + assertNull( sinkEventAttributeSet.getResolveParent() ); + sinkEventAttributeSet.setResolveParent( SinkEventAttributeSet.CENTER ); + assertNotNull( sinkEventAttributeSet.getResolveParent() ); + } + + /** + * Test of clone method, of class SinkEventAttributeSet. + */ + public void testClone() + { + Object result = sinkEventAttributeSet.clone(); + assertTrue( sinkEventAttributeSet.equals( result ) ); + + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.MONOSPACED ); + assertFalse( sinkEventAttributeSet.equals( result ) ); + + result = sinkEventAttributeSet.clone(); + assertTrue( sinkEventAttributeSet.equals( result ) ); + sinkEventAttributeSet.setResolveParent( SinkEventAttributeSet.CENTER ); + //assertFalse( sinkEventAttributeSet.equals( result ) ); + + result = sinkEventAttributeSet.clone(); + assertTrue( sinkEventAttributeSet.equals( result ) ); + sinkEventAttributeSet.setResolveParent( SinkEventAttributeSet.BOXED ); + //assertFalse( sinkEventAttributeSet.equals( result ) ); + } + + /** + * Test of hashCode method, of class SinkEventAttributeSet. + */ + public void testHashCode() + { + int oldValue = sinkEventAttributeSet.hashCode(); + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.BOLD ); + int newValue = sinkEventAttributeSet.hashCode(); + assertFalse( oldValue == newValue ); + + oldValue = newValue; + sinkEventAttributeSet.setResolveParent( SinkEventAttributeSet.CENTER ); + newValue = sinkEventAttributeSet.hashCode(); + assertFalse( oldValue == newValue ); + } + + /** + * Test of toString method, of class SinkEventAttributeSet. + */ + public void testToString() + { + String expected = ""; + assertEquals( expected, sinkEventAttributeSet.toString() ); + + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.BOXED ); + expected = " decoration=boxed"; + assertEquals( expected, sinkEventAttributeSet.toString() ); + + sinkEventAttributeSet.addAttributes( SinkEventAttributeSet.CENTER ); + expected = " decoration=boxed align=center"; + assertEquals( expected, sinkEventAttributeSet.toString() ); + } +} Propchange: maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkEventAttributeSetTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/SinkEventAttributeSetTest.java ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision"