Package com.sun.msv.reader.relax.core.checker

Source Code of com.sun.msv.reader.relax.core.checker.IdAbuseChecker

/*
* 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.reader.relax.core.checker;

import java.util.Iterator;
import java.util.Set;

import org.relaxng.datatype.Datatype;

import com.sun.msv.datatype.xsd.IDREFType;
import com.sun.msv.datatype.xsd.IDType;
import com.sun.msv.grammar.AttributeExp;
import com.sun.msv.grammar.ChoiceExp;
import com.sun.msv.grammar.ConcurExp;
import com.sun.msv.grammar.DataExp;
import com.sun.msv.grammar.ElementExp;
import com.sun.msv.grammar.Expression;
import com.sun.msv.grammar.InterleaveExp;
import com.sun.msv.grammar.ListExp;
import com.sun.msv.grammar.MixedExp;
import com.sun.msv.grammar.OneOrMoreExp;
import com.sun.msv.grammar.OtherExp;
import com.sun.msv.grammar.ReferenceExp;
import com.sun.msv.grammar.SequenceExp;
import com.sun.msv.grammar.SimpleNameClass;
import com.sun.msv.grammar.ValueExp;
import com.sun.msv.grammar.relax.AttPoolClause;
import com.sun.msv.grammar.relax.ElementRules;
import com.sun.msv.grammar.relax.HedgeRules;
import com.sun.msv.grammar.relax.RELAXExpressionVisitorVoid;
import com.sun.msv.grammar.relax.RELAXModule;
import com.sun.msv.grammar.relax.TagClause;
import com.sun.msv.reader.relax.core.RELAXCoreReader;

/**
* makes sure that ID/IDREF are not abused.
*
* RELAX has the following constraint over the use of ID/IDREF.
*
* <p>
* First, ID and IDREF can be only used as attribute values.
* They cannot be used from type attribute of elementRules.
*
* <p>
* Second, if &lt;tag&gt; clause declares directly or indirectly
* (by referencing attPool) one of its attribute as ID/IDREF type,
* it must satisfies either (or both) of the following statement.
*
* <ol>
<li>no other tag clause shares the same tag name.
<li>no other attribute of non-ID/IDREF types shares the same attribute name.
* </ol>
*
* @author <a href="mailto:kohsuke.kawaguchi@eng.sun.com">Kohsuke KAWAGUCHI</a>
*/
public class IdAbuseChecker implements RELAXExpressionVisitorVoid {
   
    /** set of Strings: tag names that are used in this module */
    private final Set tagNames = new java.util.HashSet();
    /** set of Strings: tag names that are used more than once in this module */
    private final Set overloadedNames = new java.util.HashSet();
    /** set of Strings: names of non-ID/IDREF attributes */
    private final Set nonIdAttrNames = new java.util.HashSet();
    /** set of AttributeExps: that have ID/IDREF values */
    private final Set idAttributes = new java.util.HashSet();

    private final RELAXModule module;
    private final RELAXCoreReader reader;
   
    private String currentTagName;
   
    private IdAbuseChecker(RELAXCoreReader r,RELAXModule m) {
        this.reader = r;
        this.module = m;
    }

    public static void check( RELAXCoreReader reader, RELAXModule module ) {
        new IdAbuseChecker(reader,module).run();
    }
   
    private void run() {
        Iterator itr;
        // extracts all tag names and
        // classify attribute names into
        //   (1) names that are used as ID/IDREF
        //   (2) names that are used as other datatypes.
        itr= module.tags.iterator();
        while( itr.hasNext() )
        {
            final TagClause tag = (TagClause)itr.next();
            if( tag.nameClass instanceof SimpleNameClass )
            {
                SimpleNameClass snc = (SimpleNameClass)tag.nameClass;
                if( tagNames.contains(snc.localName) )
                    overloadedNames.add(snc.localName);
                else
                    tagNames.add(snc.localName);
            }
        }
           
        // 1st filter: collect those AttributeExps which have overloaded tag names.
        itr= module.tags.iterator();
        while( itr.hasNext() ) {
            final TagClause tag = (TagClause)itr.next();
            if( tag.nameClass instanceof SimpleNameClass )
                currentTagName = ((SimpleNameClass)tag.nameClass).localName;
            else
                currentTagName = null;    // indicates wild card
           
            tag.exp.visit(this);
        }
       
        // make sure that filtered AttributeExp satisifies the second statement
        itr = idAttributes.iterator();
        while( itr.hasNext() ) {
            final AttributeExp atr = (AttributeExp)itr.next();
           
            if( atr.nameClass instanceof SimpleNameClass ) {
                final String name = ((SimpleNameClass)atr.nameClass).localName;
                if( nonIdAttrNames.contains(name) )
                    reader.reportError( RELAXCoreReader.ERR_ID_ABUSE_1, name );
            } else
                reader.reportError( RELAXCoreReader.ERR_ID_ABUSE );
        }
    }


    public void onAttribute( AttributeExp exp ) {
        if(!(exp.nameClass instanceof SimpleNameClass ))    return;
       
        Expression body = exp.exp.getExpandedExp(reader.pool);
        if(!(body instanceof DataExp ))                    return;
       
        SimpleNameClass snc = (SimpleNameClass)exp.nameClass;
        if(!snc.namespaceURI.equals(""))    return;
       
        Datatype dt = ((DataExp)body).dt;
        if( dt==IDType.theInstance || dt==IDREFType.theInstance ) {
            if( currentTagName==null
                // complex attribute name is used.
                // ID/IDREF must have an unique attribute name
            ||  overloadedNames.contains(currentTagName) )
                idAttributes.add(exp);    // possibility of abuse.
           
            // use of ID/IDREF in this way is OK.
        } else
            nonIdAttrNames.add(snc.localName);
    }
    public void onChoice( ChoiceExp exp )        { exp.exp1.visit(this);exp.exp2.visit(this); }
    public void onElement( ElementExp exp )        { throw new Error(); }
    public void onOneOrMore( OneOrMoreExp exp )    { exp.exp.visit(this); }
    public void onMixed( MixedExp exp )            { throw new Error(); }
    public void onRef( ReferenceExp exp )        { exp.exp.visit(this); }
    public void onOther( OtherExp exp )            { exp.exp.visit(this); }
    public void onEpsilon()                        {}
    public void onNullSet()                        {}
    public void onAnyString()                    {}
    public void onSequence( SequenceExp exp )    {}
    public void onData( DataExp exp )                { throw new Error(); }
    public void onValue( ValueExp exp )                { throw new Error(); }
    public void onAttPool( AttPoolClause exp )        { exp.exp.visit(this); }
    public void onTag( TagClause exp )                { throw new Error(); }
    public void onElementRules( ElementRules exp )    { throw new Error(); }
    public void onHedgeRules( HedgeRules exp )        { throw new Error(); }
    public void onInterleave( InterleaveExp exp )    { throw new Error(); }
    public void onConcur( ConcurExp exp )            { throw new Error(); }
    public void onList( ListExp exp )                { throw new Error(); }

}
TOP

Related Classes of com.sun.msv.reader.relax.core.checker.IdAbuseChecker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.