/* * @(#)$Id: FractionDigitsFacet.java,v 1.13 2002/06/24 19:57:28 kk122374 Exp $ * * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. * * This software is the proprietary information of Sun Microsystems, Inc. * Use is subject to license terms. * */ package com.sun.msv.datatype.xsd; import org.relaxng.datatype.DatatypeException; import org.relaxng.datatype.ValidationContext; /** * 'fractionDigits' facet. * * this class holds these facet information and performs validation. * * @author <a href="mailto:kohsuke.kawaguchi@eng.sun.com">Kohsuke KAWAGUCHI</a> */ public class FractionDigitsFacet extends DataTypeWithLexicalConstraintFacet { /** maximum number of fraction digits */ public final int scale; public FractionDigitsFacet( String nsUri, String typeName, XSDatatypeImpl baseType, TypeIncubator facets ) throws DatatypeException { super( nsUri, typeName, baseType, FACET_FRACTIONDIGITS, facets ); scale = facets.getNonNegativeInteger(FACET_FRACTIONDIGITS); // loosened facet check DataTypeWithFacet o = baseType.getFacetObject(FACET_FRACTIONDIGITS); if(o!=null && ((FractionDigitsFacet)o).scale < this.scale ) throw new DatatypeException( localize( ERR_LOOSENED_FACET, FACET_FRACTIONDIGITS, o.displayName() ) ); // consistency with precision is checked in XSDatatypeImpl.derive method. } protected boolean checkLexicalConstraint( String content ) { return countScale(content)<=scale; } protected void diagnoseByFacet(String content, ValidationContext context) throws DatatypeException { final int cnt = countScale(content); if(cnt<=scale) return; throw new DatatypeException( DatatypeException.UNKNOWN, localize(ERR_TOO_MUCH_SCALE, new Integer(cnt), new Integer(scale)) ); } /** count the number of fractional digits. * * this method can assume that the given literal is appropriate * as an decimal value. * * "the number of fractional digits" is defined in * http://www.w3.org/TR/xmlschema-2/#number */ final protected static int countScale( String literal ) { final int len = literal.length(); boolean skipMode = true; int count=0; int trailingZero=0; for( int i=0; i<len; i++ ) { final char ch = literal.charAt(i); if( skipMode ) { if( ch=='.' ) skipMode = false; } else { if( ch=='0' ) trailingZero++; else trailingZero=0; if( '0'<=ch && ch<='9' ) count++; } } return count-trailingZero; } }