All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.birt.report.model.parser.StylesState Maven / Gradle / Ivy

There is a newer version: 4.6.0-20160607
Show newest version

package org.eclipse.birt.report.model.parser;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.eclipse.birt.report.model.core.DesignElement;
import org.eclipse.birt.report.model.core.NameSpace;
import org.eclipse.birt.report.model.core.namespace.INameHelper;
import org.eclipse.birt.report.model.core.namespace.NameExecutor;
import org.eclipse.birt.report.model.elements.ReportDesign;
import org.eclipse.birt.report.model.util.AbstractParseState;
import org.eclipse.birt.report.model.util.VersionUtil;
import org.xml.sax.SAXException;

/**
 * Parses the contents of the list of styles. This can be called by ReportState
 * and ThemeState.
 */
public class StylesState extends SlotState
{

	// ( c >= 0 && c <= 29 ) || ( c >= 31 && c <= 47 )
	// ( c >= 58 && c <= 64 )
	// ( c >= 91 && c <= 96 )
	// ( c >= 123 && c <= 199 ) )
	private static final String STYLE_NAME_FORBIDDEN_PATTERN = "[\\x00-\\x1D]|[\\x1F-\\x2F]|[\\x3A-\\x40]|[\\x5B-\\x60]|[\\x7B-\\xC7]"; //$NON-NLS-1$
	private static final String STYLE_NAME_START = "([a-z]|[^\0-\177]|((\\[0-9a-f]{1,6}[ \n\r\t\f]?)|\\[ -~\200-\4177777]))"; //$NON-NLS-1$
	public static final Pattern styleNameStartPattern = Pattern.compile(
			STYLE_NAME_START, Pattern.CASE_INSENSITIVE );

	private static final String MIDDLE_LINE = "-"; //$NON-NLS-1$
	private static final String REPLACE_LETTER = "s"; //$NON-NLS-1$

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.birt.report.model.util.AbstractParseState#startElement
	 * (java.lang.String)
	 */

	public StylesState( ModuleParserHandler handler, DesignElement container,
			int slot )
	{
		super( handler, container, slot );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.birt.report.model.util.AbstractParseState#startElement
	 * (java.lang.String)
	 */

	public AbstractParseState startElement( String tagName )
	{
		int tagValue = tagName.toLowerCase( ).hashCode( );
		if ( ParserSchemaConstants.STYLE_TAG == tagValue )
			return new StyleState( handler, container, slotID );
		return super.startElement( tagName );
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.birt.report.model.util.AbstractParseState#end()
	 */
	public void end( ) throws SAXException
	{
		// if version < 3.2.19, do some compatibilities about style name; from
		// 3.2.19, all style name is case-insensitive
		if ( handler.versionNumber < VersionUtil.VERSION_3_2_19 )
		{
			List styles = container.getSlot( slotID )
					.getContents( );
			checkStyleName( styles );
		}
		super.end( );
	}

	/**
	 * Checks the name of the styles in the list. If some style has the
	 * duplicate name except the different cases, this method will rename it to
	 * have different name even ignoring the cases.
	 * 
	 * @param styles
	 */
	private void checkStyleName( List styles )
	{
		if ( styles != null && !styles.isEmpty( ) )
		{
			// get the built style name map
			Map styleMap = buildNameMap( styles );

			for ( int i = 0; i < styles.size( ); i++ )
			{
				DesignElement style = styles.get( i );
				String oldName = style.getName( );

				// we need NOT check the validation of the style name, Engine
				// should ensure the validation of the style name in html output
				//checkValidation( style, styleMap );

				NameSpace ns = null;
				if ( style.getContainer( ) instanceof ReportDesign )
				{
					NameExecutor executor = new NameExecutor(
							(ReportDesign) style.getContainer( ), style );
					ns = executor.getNameSpace( );
				}

				// check the unique
				String styleName = style.getName( );
				String lowerCaseName = styleName.toLowerCase( );
				if ( styleMap.containsKey( lowerCaseName )
						&& styleMap.get( lowerCaseName ) != style )
				{
					String baseName = styleName;
					String name = styleName;
					int index = 0;
					// style name is case-insensitive
					while ( styleMap.containsKey( lowerCaseName )
							&& styleMap.get( lowerCaseName ) != style )
					{
						name = baseName + ++index;
						lowerCaseName = name.toLowerCase( );
					}

					// rename the style and then add to the name space
					style.setName( name );
					if ( ns != null && !ns.contains( name.toLowerCase( ) ) )
						ns.insert( style );
					// do the cache
					if ( !styleMap.containsKey( name.toLowerCase( ) ) )
						styleMap.put( name.toLowerCase( ), style );
					// remove the old name
					if ( styleMap.get( styleName.toLowerCase( ) ) == style )
						styleMap.remove( styleName.toLowerCase( ) );

					// set-up the oldName/newName map(rename relationship) to
					// help the resolve the style for report items
					Map nameMaps = (Map) handler.tempValue
							.get( container );
					if ( nameMaps == null )
					{
						nameMaps = new HashMap( );
						handler.tempValue.put( container, nameMaps );
					}
					nameMaps.put( oldName, name );
				}
				else
				{
					if ( ns != null && !ns.contains( lowerCaseName ) )
						ns.insert( style );
				}
			}
		}

	}

	/**
	 * Builds a map for the style elements. Key is the lower-case name for the
	 * element and value is the first element that has the with the name for the
	 * key. If two elements have the same name except the different cases, we
	 * will store the first element in the map and ignore others.
	 * 
	 * @param styles
	 * @return
	 */
	private Map buildNameMap( List styles )
	{
		Map styleMap = new HashMap( );
		for ( int i = 0; i < styles.size( ); i++ )
		{
			DesignElement style = styles.get( i );
			String styleName = style.getName( );
			String lowerName = styleName.toLowerCase( );
			if ( !styleMap.containsKey( lowerName ) )
				styleMap.put( lowerName, style );
		}

		return styleMap;
	}

//	private void checkValidation( DesignElement style,
//			Map styleMap )
//	{
//		String styleName = style.getName( );
//
//		// first, check the validation of the name
//		if ( !NameCommand.styleNamePattern.matcher( styleName ).matches( ) )
//		{
//			String newName = styleName;
//			newName = newName.replaceAll( STYLE_NAME_FORBIDDEN_PATTERN,
//					MIDDLE_LINE );
//
//			// if the new name is not start with letters, it is illegal too
//			String firstChar = newName.substring( 0, 1 );
//			if ( !styleNameStartPattern.matcher( firstChar ).matches( ) )
//			{
//				if ( newName.length( ) <= 1 )
//					newName = REPLACE_LETTER;
//				else
//					newName = REPLACE_LETTER + newName.substring( 1 );
//			}
//
//			// TODO: ensure the new name is valid for the css2 spec; the
//			// worst way is setting the name to NULL and then calling
//			// makeUnique to generate a valid and unique name
//			assert NameCommand.styleNamePattern.matcher( newName ).matches( );
//			style.setName( newName );
//			// set-up name-map
//			Map nameMap = (Map) handler.tempValue
//					.get( style.getContainer( ) );
//			if ( nameMap == null )
//			{
//				nameMap = new HashMap( );
//				handler.tempValue.put( style.getContainer( ), nameMap );
//			}
//			nameMap.put( styleName, newName );
//
//			if ( !styleMap.containsKey( newName.toLowerCase( ) ) )
//				styleMap.put( newName.toLowerCase( ), style );
//			// remove the old name
//			if ( styleMap.get( styleName.toLowerCase( ) ) == style )
//				styleMap.remove( styleName.toLowerCase( ) );
//		}
//	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy