Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2001-2013 Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.sun.msv.verifier.regexp;
import java.util.StringTokenizer;
import org.relaxng.datatype.Datatype;
import com.sun.msv.datatype.xsd.StringType;
import com.sun.msv.grammar.DataExp;
import com.sun.msv.grammar.Expression;
import com.sun.msv.grammar.IDContextProvider2;
import com.sun.msv.grammar.ListExp;
import com.sun.msv.grammar.ValueExp;
import com.sun.msv.util.DatatypeRef;
/**
* chunk of string.
*
* ID validation depends on the immutability of this object.
*
* @author Kohsuke KAWAGUCHI
*/
public class StringToken extends Token {
public final String literal;
public final IDContextProvider2 context;
protected final ResidualCalculator resCalc;
protected final boolean ignorable;
/**
* if this field is non-null,
* this field will receive assigned DataType object.
*/
public DatatypeRef refType;
protected boolean saturated = false;
private static final Datatype[] ignoredType = new Datatype[0];
public StringToken(REDocumentDeclaration docDecl, String literal, IDContextProvider2 context) {
this(docDecl.resCalc, literal, context, null);
}
public StringToken(REDocumentDeclaration docDecl, String literal, IDContextProvider2 context, DatatypeRef refType) {
this(docDecl.resCalc, literal, context, refType);
}
public StringToken(ResidualCalculator resCalc, String literal, IDContextProvider2 context, DatatypeRef refType) {
this.resCalc = resCalc;
this.literal = literal;
this.context = context;
this.refType = refType;
this.ignorable = literal.trim().length() == 0;
if (ignorable && refType != null)
refType.types = ignoredType;
}
/** DataExp can consume this token if its datatype can accept this string */
public boolean match(DataExp exp) {
if (!exp.dt.isValid(literal, context))
return false; // not accepted.
if (exp.except != Expression.nullSet) {
if (resCalc.calcResidual(exp.except, this).isEpsilonReducible())
// handling whitespace correcly requires isEpsilonReducible()
// with the following test case
//
// with "".
return false; // this token is accepted by its 'except' clause
}
// this type accepts me.
if (refType != null)
assignType(exp.dt);
// if the type has ID semantics, report it.
if (exp.dt.getIdType() != Datatype.ID_TYPE_NULL && context != null)
// context can be legally null when this datatype is not context dependent.
context.onID(exp.dt, this);
return true;
}
public boolean match(ValueExp exp) {
Object thisValue = exp.dt.createValue(literal, context);
if (!exp.dt.sameValue(thisValue, exp.value))
return false;
// this type accepts me.
if (refType != null)
assignType(exp.dt);
// if the type has ID semantics, report it.
if (exp.dt.getIdType() != Datatype.ID_TYPE_NULL && context != null)
// context can be legally null when this datatype is not context dependent.
context.onID(exp.dt, this);
return true;
}
/** ListExp can consume this token if its pattern accepts this string */
public boolean match(ListExp exp) {
StringTokenizer tokens = new StringTokenizer(literal);
Expression residual = exp.exp;
// if the application needs type information,
// collect them from children.
DatatypeRef dtRef = null;
Datatype[] childTypes = null;
int cnt = 0;
if (this.refType != null) {
dtRef = new DatatypeRef();
childTypes = new Datatype[tokens.countTokens()];
}
while (tokens.hasMoreTokens()) {
StringToken child = createChildStringToken(tokens.nextToken(), dtRef);
residual = resCalc.calcResidual(residual, child);
if (residual == Expression.nullSet)
// the expression is failed to accept this item.
return false;
if (dtRef != null) {
if (dtRef.types == null) {
// failed to assign type. bail out.
saturated = true;
refType.types = null;
dtRef = null;
} else {
// type is successfully assigned for this child.
if (dtRef.types.length != 1)
// the current RELAX NG prohibits to nest patterns.
// Thus it's not possible for this child to return more than one type.
throw new Error();
childTypes[cnt++] = dtRef.types[0];
}
}
}
if (!residual.isEpsilonReducible())
// some expressions are still left. failed to accept this string.
return false;
// this accepts this string.
if (childTypes != null) {
// assign datatype
if (saturated)
// a type is already assigned. That means this string has more than one type.
// so bail out.
refType.types = null;
else
refType.types = childTypes;
saturated = true;
}
return true;
}
protected StringToken createChildStringToken(String literal, DatatypeRef dtRef) {
return new StringToken(resCalc, literal, context, dtRef);
}
// anyString can match any string
public boolean matchAnyString() {
if (refType != null)
assignType(StringType.theInstance);
return true;
}
private void assignType(Datatype dt) {
if (saturated) {
if (refType.types != null && (refType.types[0] != dt || refType.types.length != 1))
// different types are assigned. roll back to null
refType.types = null;
} else {
// this is the first assignment. remember this value.
refType.types = new Datatype[] { dt };
saturated = true;
}
}
/** checks if this token is ignorable.
*
* StringToken is ignorable when it matches [ \t\r\n]*
*/
boolean isIgnorable() {
return ignorable;
}
}