public void onElement( ElementExp exp ) {
if(!elements.add(exp))
return; // this element has already processed.
StringPair _en = elementName;
IDAttMap _curAtts = curAtts;
ElementExp _curElm = curElm;
NameClass nc = exp.getNameClass();
if(nc instanceof SimpleNameClass) {
elementName = new StringPair((SimpleNameClass)nc);
curAtts = (IDAttMap)name2value.get(elementName); // maybe null.
} else
elementName = null;
curElm = exp;
// System.out.println("tested:" +
// com.sun.msv.grammar.util.ExpressionPrinter.printContentModel(
// exp.contentModel.visit(remover)));
// visit the content model, but remove reference exps first.
exp.contentModel.visit(remover).visit(this);
if( elementName!=null && curAtts!=null )
name2value.put(elementName,curAtts);
elementName = _en;
curAtts = _curAtts;
curElm = _curElm;
}
public void onAttribute( AttributeExp exp ) {
if(!(exp.exp instanceof DataOrValueExp)) {
// otherwise visit the content model normally
// so that we can find any invalid use of ID/IDREF types.
exp.exp.visit(this);
return;
}
DataOrValueExp texp = (DataOrValueExp)exp.exp;
if(texp.getType().getIdType()==Datatype.ID_TYPE_NULL) {
// if this type is not ID/IDREF type, then it's OK
return;
}
if(!(exp.nameClass instanceof SimpleNameClass)) {
reportCompError(
new Locator[]{reader.getDeclaredLocationOf(exp)},
CERR_ID_TYPE_WITH_NON_SIMPLE_ATTNAME,
new Object[]{
texp.getName().localName,
getSemanticsStr(texp.getType().getIdType())} );
return;
}
StringPair attName = new StringPair((SimpleNameClass)exp.nameClass);
if( elementName==null ) {
reportCompError(
new Locator[]{
reader.getDeclaredLocationOf(exp),
reader.getDeclaredLocationOf(curElm)},
CERR_ID_TYPE_WITH_NON_SIMPLE_ELEMENTNAME,
new Object[]{
texp.getName().localName,
getSemanticsStr(texp.getType().getIdType())} );
return;
}
// the enclosing attribute name is simple, and
// the enclosing element name is simple, too.
// this is the only place we can have ID/IDREF types.
// store that this attribute is used for ID/IDREF.
if(curAtts==null)
curAtts = new IDAttMap(curElm);
curAtts.idatts.put(attName,texp.getName());
}
public void onData( DataExp exp ) { checkIdType(exp); }
public void onValue( ValueExp exp ) { checkIdType(exp); }
private void checkIdType( DataOrValueExp exp ) {
if(exp.getType().getIdType()!=Datatype.ID_TYPE_NULL) {
// ID/IDREF type in all other locations are subject to
// a compatibility error.
reportCompError(
new Locator[]{reader.getDeclaredLocationOf(exp)},
CERR_MALPLACED_ID_TYPE,
new Object[]{
exp.getName().localName,
getSemanticsStr(exp.getType().getIdType())});
}
}
});
if(!grammar.isIDcompatible)
// if an compatibility error has been found, abort further check.
return;
/*
2nd pass
========
make sure that no other attributes are competing with id attributes.
*/
Iterator itr = elements.iterator();
final Vector vec = new Vector(); // IDAttMaps of the competing elements
while( itr.hasNext() ) {
final ElementExp eexp = (ElementExp)itr.next();
// list up all competing elements.
vec.clear();
Iterator jtr = name2value.entrySet().iterator();
while(jtr.hasNext()) {
Map.Entry e = (Map.Entry)jtr.next();
if( eexp.getNameClass().accepts((StringPair)e.getKey()) )
vec.add( e.getValue()/*IDAttMap*/ );
}
if(vec.size()==0)
continue; // this element does not comete with anything.
// no need to check
// make sure that no attributes are actually competing.
eexp.contentModel.visit(remover).visit( new ExpressionWalker() {
public void onElement( ElementExp exp ) {
return; // do not recurse child elements.
}
public void onAttribute( AttributeExp exp ) {
if(exp.exp instanceof DataOrValueExp) {
DataOrValueExp texp = (DataOrValueExp)exp.exp;
if(texp.getType().getIdType()!=Datatype.ID_TYPE_NULL) {
// if the schema is OK with the 1st pass check
// and if this element contains the ID type, then
// this element must be simple-named.
// so at most one IDAttMap can match it.
_assert(vec.size()==1);
// by the same assumption, the attribute name must be
// simple.
SimpleNameClass attName = (SimpleNameClass)exp.nameClass;
IDAttMap iam = (IDAttMap)vec.get(0);
if(!texp.getName().equals(iam.idatts.get(new StringPair(attName))))
reportCompError(
new Locator[]{
reader.getDeclaredLocationOf(exp),
reader.getDeclaredLocationOf(iam.sampleDecl)},
CERR_COMPETING,