/*
* @(#)$Id: TotalDigitsFacet.java,v 1.14 2002/10/18 03:14:11 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;
/**
* 'totalDigits' facet.
*
* this class holds these facet information and performs validation.
*
* @author <a href="mailto:kohsuke.kawaguchi@eng.sun.com">Kohsuke KAWAGUCHI</a>
*/
public class TotalDigitsFacet extends DataTypeWithLexicalConstraintFacet {
/** maximum number of total digits. */
public final int precision;
public TotalDigitsFacet( String nsUri, String typeName, XSDatatypeImpl baseType, TypeIncubator facets )
throws DatatypeException {
super( nsUri, typeName, baseType, FACET_TOTALDIGITS, facets );
precision = facets.getPositiveInteger(FACET_TOTALDIGITS);
// loosened facet check
DataTypeWithFacet o = baseType.getFacetObject(FACET_TOTALDIGITS);
if(o!=null && ((TotalDigitsFacet)o).precision < this.precision )
throw new DatatypeException( localize( ERR_LOOSENED_FACET,
FACET_TOTALDIGITS, o.displayName() ) );
// consistency with scale is checked in XSDatatypeImpl.derive method.
}
protected boolean checkLexicalConstraint( String content ) {
return countPrecision(content)<=precision;
}
protected void diagnoseByFacet(String content, ValidationContext context) throws DatatypeException {
final int cnt = countPrecision(content);
if( cnt<=precision ) return;
throw new DatatypeException( DatatypeException.UNKNOWN,
localize(ERR_TOO_MUCH_PRECISION, new Integer(cnt), new Integer(precision)) );
}
/** counts the number of digits */
protected static int countPrecision( String literal ) {
final int len = literal.length();
boolean skipMode = true;
boolean seenDot = false;
int count=0;
int trailingZero=0;
for( int i=0; i<len; i++ ) {
final char ch = literal.charAt(i);
if(ch=='.') {
skipMode = false;// digits after '.' is considered significant.
seenDot = true;
}
if( skipMode ) {
// in skip mode, leading zeros are skipped
if( '1'<=ch && ch<='9' ) {
count++;
skipMode = false;
}
} else {
if( seenDot && ch=='0' ) trailingZero++;
else trailingZero=0;
if( '0'<=ch && ch<='9' )
count++;
}
}
return count-trailingZero;
}
}