/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.core.imagemap.parser;
import org.pentaho.reporting.engine.classic.core.imagemap.AbstractImageMapEntry;
import org.pentaho.reporting.engine.classic.core.imagemap.CircleImageMapEntry;
import org.pentaho.reporting.engine.classic.core.imagemap.DefaultImageMapEntry;
import org.pentaho.reporting.engine.classic.core.imagemap.PolygonImageMapEntry;
import org.pentaho.reporting.engine.classic.core.imagemap.RectangleImageMapEntry;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.xmlns.parser.AbstractXmlReadHandler;
import org.pentaho.reporting.libraries.xmlns.parser.ParseException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import java.util.StringTokenizer;
public class AreaReadHandler extends AbstractXmlReadHandler {
private AbstractImageMapEntry mapEntry;
private static final float[] EMPTY_FLOATS = new float[0];
public AreaReadHandler() {
}
/**
* Starts parsing.
*
* @param attrs
* the attributes.
* @throws org.xml.sax.SAXException
* if there is a parsing error.
*/
protected void startParsing( final Attributes attrs ) throws SAXException {
super.startParsing( attrs );
final String shape = attrs.getValue( getUri(), "shape" );
final String coordinates = attrs.getValue( getUri(), "coords" );
final float[] coords = parseFloatArray( coordinates );
mapEntry = createMapEntry( shape, coords );
final int length = attrs.getLength();
for ( int i = 0; i < length; i++ ) {
if ( "xmlns".equals( attrs.getQName( i ) ) || attrs.getQName( i ).startsWith( "xmlns:" ) ) {
// workaround for buggy parsers
continue;
}
final String name = attrs.getLocalName( i );
if ( name.indexOf( ':' ) > -1 ) {
// attribute with ':' are not valid and indicate a namespace definition or so
continue;
}
final String namespace = attrs.getURI( i );
final String attributeValue = attrs.getValue( i );
if ( isSameNamespace( namespace ) ) {
if ( "shape".equals( name ) ) {
continue;
}
if ( "coords".equals( name ) ) {
continue;
}
}
mapEntry.setAttribute( namespace, name, attributeValue );
}
}
private AbstractImageMapEntry createMapEntry( final String type, final float[] coordinates ) throws ParseException {
if ( "rect".equals( type ) ) {
if ( coordinates.length != 4 ) {
throw new ParseException( "Rect-shape needs four coordinate-values", getLocator() );
}
return new RectangleImageMapEntry( coordinates[0], coordinates[1], coordinates[2], coordinates[3] );
}
if ( "circle".equals( type ) ) {
if ( coordinates.length != 3 ) {
throw new ParseException( "Circle-shape needs three coordinate-values", getLocator() );
}
return new CircleImageMapEntry( coordinates[0], coordinates[1], coordinates[2] );
}
if ( "poly".equals( type ) ) {
if ( ( coordinates.length % 2 ) != 0 ) {
throw new ParseException( "Polygon-shape needs an even number of coordinate-values", getLocator() );
}
return new PolygonImageMapEntry( coordinates );
}
if ( "default".equals( type ) ) {
return new DefaultImageMapEntry();
}
if ( coordinates.length != 4 ) {
throw new ParseException( "Implied Rect-shape needs four coordinate-values", getLocator() );
}
return new RectangleImageMapEntry( coordinates[0], coordinates[1], coordinates[2], coordinates[3] );
}
/**
* Returns the object for this element or null, if this element does not create an object.
*
* @return the object.
* @throws org.xml.sax.SAXException
* if an parser error occured.
*/
public Object getObject() throws SAXException {
return mapEntry;
}
/**
* Converts the given string into a array of <code>BigDecimal</code> numbers using the given separator as splitting
* argument.<br/>
* Take care that <code>BigDecimal</code> string constructor do not support inputs like "10f", "5d" ...
*
* @param s
* the string to be converted.
* @return the array of numbers produced from the string.
* @throws org.pentaho.reporting.libraries.xmlns.parser.ParseException
* if the string <code>s</code> does not contain valid numbers.
*/
private float[] parseFloatArray( final String s ) throws ParseException {
if ( StringUtils.isEmpty( s ) ) {
return EMPTY_FLOATS;
}
try {
final StringTokenizer stringTokenizer = new StringTokenizer( s, "," );
final float[] ret = new float[stringTokenizer.countTokens()];
int i = 0;
while ( stringTokenizer.hasMoreTokens() ) {
final String val = stringTokenizer.nextToken().trim();
ret[i] = Float.parseFloat( val );
i += 1;
}
return ret;
} catch ( final NumberFormatException nfe ) {
// re-throw the exception
throw new ParseException( "Unable to convert array-text to real array.", getLocator() );
}
}
}