blob: 27edd430fc74f821ae40d53c7b46645825b269fd [file] [log] [blame]
package org.apache.maven.doxia.sink.impl;
/*
* 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 java.util.Arrays;
import javax.swing.text.AttributeSet;
import javax.swing.text.MutableAttributeSet;
import org.apache.maven.doxia.markup.Markup;
import org.apache.maven.doxia.sink.SinkEventAttributes;
/**
* Collection of common utility methods for sinks.
*
* @author ltheussl
* @version $Id$
* @since 1.1
*/
public class SinkUtils
{
/** Do not instantiate. */
private SinkUtils()
{
// Utility class
}
/**
* The set of base attributes.
*/
public static final String[] SINK_BASE_ATTRIBUTES =
{
SinkEventAttributes.CLASS, SinkEventAttributes.ID, SinkEventAttributes.LANG,
SinkEventAttributes.STYLE, SinkEventAttributes.TITLE
};
/**
* The attributes that are supported for the br tag.
*/
public static final String[] SINK_BR_ATTRIBUTES =
{
SinkEventAttributes.CLASS, SinkEventAttributes.ID,
SinkEventAttributes.STYLE, SinkEventAttributes.TITLE
};
/**
* The attributes that are supported for the <img> tag.
*/
public static final String[] SINK_IMG_ATTRIBUTES;
/**
* The attributes that are supported for the section tags, like <p>, <h2>, <div>.
*/
public static final String[] SINK_SECTION_ATTRIBUTES;
/**
* The attributes that are supported for the <div> and <pre> tags.
*/
public static final String[] SINK_VERBATIM_ATTRIBUTES;
/**
* The attributes that are supported for the <hr> tag.
*/
public static final String[] SINK_HR_ATTRIBUTES;
/**
* The attributes that are supported for the <a> tag.
*/
public static final String[] SINK_LINK_ATTRIBUTES;
/**
* The attributes that are supported for the <table> tag.
*/
public static final String[] SINK_TABLE_ATTRIBUTES;
/**
* The attributes that are supported for the <td> and <th> tags.
*/
public static final String[] SINK_TD_ATTRIBUTES;
/**
* The attributes that are supported for the <tr> tag.
*/
public static final String[] SINK_TR_ATTRIBUTES;
private static final String[] IMG_ATTRIBUTES =
{
SinkEventAttributes.ALIGN, SinkEventAttributes.ALT, SinkEventAttributes.BORDER,
SinkEventAttributes.HEIGHT, SinkEventAttributes.HSPACE, SinkEventAttributes.ISMAP,
SinkEventAttributes.SRC, SinkEventAttributes.USEMAP, SinkEventAttributes.VSPACE,
SinkEventAttributes.WIDTH
};
private static final String[] HR_ATTRIBUTES =
{
SinkEventAttributes.ALIGN, SinkEventAttributes.NOSHADE, SinkEventAttributes.SIZE,
SinkEventAttributes.WIDTH
};
private static final String[] LINK_ATTRIBUTES =
{
SinkEventAttributes.CHARSET, SinkEventAttributes.COORDS, SinkEventAttributes.HREF,
SinkEventAttributes.HREFLANG, SinkEventAttributes.REL, SinkEventAttributes.REV,
SinkEventAttributes.SHAPE, SinkEventAttributes.TARGET, SinkEventAttributes.TYPE
};
private static final String[] TABLE_ATTRIBUTES =
{
SinkEventAttributes.ALIGN, SinkEventAttributes.BGCOLOR, SinkEventAttributes.BORDER,
SinkEventAttributes.CELLPADDING, SinkEventAttributes.CELLSPACING, SinkEventAttributes.FRAME,
SinkEventAttributes.RULES, SinkEventAttributes.SUMMARY, SinkEventAttributes.WIDTH
};
private static final String[] TABLE_CELL_ATTRIBUTES =
{
SinkEventAttributes.ABBRV, SinkEventAttributes.ALIGN, SinkEventAttributes.AXIS,
SinkEventAttributes.BGCOLOR, SinkEventAttributes.COLSPAN, SinkEventAttributes.HEADERS,
SinkEventAttributes.HEIGHT, SinkEventAttributes.NOWRAP, SinkEventAttributes.ROWSPAN,
SinkEventAttributes.SCOPE, SinkEventAttributes.VALIGN, SinkEventAttributes.WIDTH
};
static
{
SINK_IMG_ATTRIBUTES = join( SINK_BASE_ATTRIBUTES, IMG_ATTRIBUTES );
SINK_SECTION_ATTRIBUTES =
join( SINK_BASE_ATTRIBUTES, new String[] {SinkEventAttributes.ALIGN} );
SINK_VERBATIM_ATTRIBUTES =
join( SINK_BASE_ATTRIBUTES,
new String[] {SinkEventAttributes.ALIGN, SinkEventAttributes.DECORATION, SinkEventAttributes.WIDTH} );
SINK_HR_ATTRIBUTES = join( SINK_BASE_ATTRIBUTES, HR_ATTRIBUTES );
SINK_LINK_ATTRIBUTES = join( SINK_BASE_ATTRIBUTES, LINK_ATTRIBUTES );
SINK_TABLE_ATTRIBUTES = join( SINK_BASE_ATTRIBUTES, TABLE_ATTRIBUTES );
SINK_TR_ATTRIBUTES =
join( SINK_BASE_ATTRIBUTES,
new String[] {SinkEventAttributes.ALIGN, SinkEventAttributes.BGCOLOR, SinkEventAttributes.VALIGN} );
SINK_TD_ATTRIBUTES = join( SINK_BASE_ATTRIBUTES, TABLE_CELL_ATTRIBUTES );
}
private static String[] join( String[] a, String[] b )
{
String[] temp = new String[a.length + b.length];
System.arraycopy( a, 0, temp, 0, a.length );
System.arraycopy( b, 0, temp, a.length, b.length );
Arrays.sort( temp ); // necessary for binary searches in filterAttributes()
return temp;
}
/**
* Utility method to get an AttributeSet as a String.
* The resulting String is in the form ' name1="value1" name2="value2" ...',
* ie it can be appended directly to an xml start tag. Attribute values that are itself
* AttributeSets are ignored unless the Attribute name is SinkEventAttributeSet.STYLE,
* in which case they are written as outlined at
* {@link org.apache.maven.doxia.sink.SinkEventAttributes#STYLE SinkEventAttributes.STYLE}.
* All other keys and values are written as Strings.
*
* @param att The AttributeSet. May be null, in which case an empty String is returned.
* @return the AttributeSet as a String in a form that can be appended to an xml start tag.
*/
public static String getAttributeString( AttributeSet att )
{
if ( att == null )
{
return "";
}
StringBuilder sb = new StringBuilder();
Enumeration<?> names = att.getAttributeNames();
while ( names.hasMoreElements() )
{
Object key = names.nextElement();
Object value = att.getAttribute( key );
if ( value instanceof AttributeSet )
{
// Other AttributeSets are ignored
if ( SinkEventAttributes.STYLE.equals( key.toString() ) )
{
sb.append( Markup.SPACE ).append( key.toString() ).append( Markup.EQUAL )
.append( Markup.QUOTE ).append( asCssString( (AttributeSet) value ) )
.append( Markup.QUOTE );
}
}
else
{
sb.append( Markup.SPACE ).append( key.toString() ).append( Markup.EQUAL )
.append( Markup.QUOTE ).append( value.toString() ).append( Markup.QUOTE );
}
}
return sb.toString();
}
private static String asCssString( AttributeSet att )
{
StringBuilder sb = new StringBuilder();
Enumeration<?> names = att.getAttributeNames();
while ( names.hasMoreElements() )
{
Object key = names.nextElement();
Object value = att.getAttribute( key );
// don't go recursive
if ( !( value instanceof AttributeSet ) )
{
sb.append( key.toString() ).append( Markup.COLON )
.append( Markup.SPACE ).append( value.toString() );
if ( names.hasMoreElements() )
{
sb.append( Markup.SEMICOLON ).append( Markup.SPACE );
}
}
}
return sb.toString();
}
/**
* Filters the given AttributeSet.
* Removes all attributes whose name (key) is not contained in the sorted array valids.
*
* @param attributes The AttributeSet to filter. The String values of Attribute names
* are compared to the elements of the valids array.
* @param valids a sorted array of attribute names that are to be kept in the resulting AttributeSet.
* <b>Note:</b> a binary search is employed, so the array has to be sorted for correct results.
* @return A filtered MutableAttributeSet object. Returns null if the input AttributeSet is null.
* If the array of valids is either null or empty, an empty AttributeSet is returned.
*/
public static MutableAttributeSet filterAttributes( AttributeSet attributes, String[] valids )
{
if ( attributes == null )
{
return null;
}
if ( valids == null || valids.length == 0 )
{
return new SinkEventAttributeSet( 0 );
}
MutableAttributeSet atts = new SinkEventAttributeSet( attributes.getAttributeCount() );
Enumeration<?> names = attributes.getAttributeNames();
while ( names.hasMoreElements() )
{
String key = names.nextElement().toString();
if ( Arrays.binarySearch( valids, key ) >= 0 )
{
atts.addAttribute( key, attributes.getAttribute( key ) );
}
}
return atts;
}
}