/*
* @(#)$Id: ExportedHedgeRuleChecker.java,v 1.8 2001/10/18 23:52:13 Bear 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.reader.relax.core.checker;
import com.sun.msv.grammar.*;
import com.sun.msv.grammar.relax.*;
import java.util.Stack;
/**
* the purpose of this function object is to make sure
* that the expression does not contain references to modules
* other than one specified by this variable.
*
* @author <a href="mailto:kohsuke.kawaguchi@eng.sun.com">Kohsuke KAWAGUCHI</a>
*/
public final class ExportedHedgeRuleChecker implements RELAXExpressionVisitorBoolean
{
private final RELAXModule module;
public ExportedHedgeRuleChecker( RELAXModule module ) { this.module = module; }
/**
* traversal stack.
*
* This object keeps track of how hedgeRules are visited so that
* detailed error message can be provided when an error is found.
*
* Say if you start from hr1, hr1 refers hr2, hr2 refers hr3,
* and hr3 has a reference to the other module, this stack is
* {hr1,hr2,hr3} when an error is found.
*/
private final Stack traversalStack = new Stack();
public ReferenceExp[] errorSnapshot = null;
public boolean onAttribute( AttributeExp exp ) { return true; }
public boolean onChoice( ChoiceExp exp ) { return exp.exp1.visit(this) && exp.exp2.visit(this); }
public boolean onSequence( SequenceExp exp ) { return exp.exp1.visit(this) && exp.exp2.visit(this); }
public boolean onElement( ElementExp exp ) { return true; }
public boolean onOneOrMore( OneOrMoreExp exp ) { return exp.exp.visit(this); }
public boolean onMixed( MixedExp exp ) { return exp.exp.visit(this); }
public boolean onRef( ReferenceExp exp ) { throw new Error(); } // should never be called
public boolean onOther( OtherExp exp ) { return exp.exp.visit(this); }
public boolean onEpsilon() { return true; }
public boolean onNullSet() { return true; }
public boolean onAnyString() { return true; }
public boolean onData( DataExp exp ) { return true; }
public boolean onValue( ValueExp exp ) { return true; }
public boolean onAttPool( AttPoolClause exp ) { throw new Error(); } // should never be called
public boolean onTag( TagClause exp ) { throw new Error(); } // should never be called
// these two shall never be called in case of RELAX.
public boolean onInterleave( InterleaveExp exp ) { throw new Error(); }
public boolean onConcur( ConcurExp exp ) { throw new Error(); }
public boolean onList( ListExp exp ) { throw new Error(); }
public boolean onElementRules( ElementRules exp ) {
if(exp.ownerModule==module) return true;
takeSnapshot(exp);
return false;
}
public boolean onHedgeRules( HedgeRules exp ) {
if( exp.ownerModule!=module ) { // reference to the other namespace
takeSnapshot(exp);
return false;
}
traversalStack.push(exp);
// we have to make sure the same thing for this referenced hedgeRule.
boolean r = exp.exp.visit(this);
traversalStack.pop();
return r;
}
/**
* takes a snap shot of traversal to this.errorSnapshot
* so that the user will know what references cause this problem.
*/
private void takeSnapshot( ReferenceExp lastExp ) {
errorSnapshot = new ReferenceExp[ traversalStack.size()+1 ];
traversalStack.toArray(errorSnapshot);
errorSnapshot[errorSnapshot.length-1] = lastExp;
}
}