aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.tools.internal.xjc.reader.xmlschema; aoqi@0: aoqi@0: import java.util.HashSet; aoqi@0: import java.util.Iterator; aoqi@0: import java.util.Map; aoqi@0: import java.util.Set; aoqi@0: aoqi@0: import com.sun.tools.internal.xjc.reader.Const; aoqi@0: import com.sun.tools.internal.xjc.reader.Ring; aoqi@0: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration; aoqi@0: import com.sun.xml.internal.bind.v2.WellKnownNamespace; aoqi@0: import com.sun.xml.internal.xsom.XSAnnotation; aoqi@0: import com.sun.xml.internal.xsom.XSAttContainer; aoqi@0: import com.sun.xml.internal.xsom.XSAttGroupDecl; aoqi@0: import com.sun.xml.internal.xsom.XSAttributeDecl; aoqi@0: import com.sun.xml.internal.xsom.XSAttributeUse; aoqi@0: import com.sun.xml.internal.xsom.XSComplexType; aoqi@0: import com.sun.xml.internal.xsom.XSComponent; aoqi@0: import com.sun.xml.internal.xsom.XSContentType; aoqi@0: import com.sun.xml.internal.xsom.XSElementDecl; aoqi@0: import com.sun.xml.internal.xsom.XSFacet; aoqi@0: import com.sun.xml.internal.xsom.XSIdentityConstraint; aoqi@0: import com.sun.xml.internal.xsom.XSListSimpleType; aoqi@0: import com.sun.xml.internal.xsom.XSModelGroup; aoqi@0: import com.sun.xml.internal.xsom.XSModelGroupDecl; aoqi@0: import com.sun.xml.internal.xsom.XSNotation; aoqi@0: import com.sun.xml.internal.xsom.XSParticle; aoqi@0: import com.sun.xml.internal.xsom.XSRestrictionSimpleType; aoqi@0: import com.sun.xml.internal.xsom.XSSchema; aoqi@0: import com.sun.xml.internal.xsom.XSSchemaSet; aoqi@0: import com.sun.xml.internal.xsom.XSSimpleType; aoqi@0: import com.sun.xml.internal.xsom.XSUnionSimpleType; aoqi@0: import com.sun.xml.internal.xsom.XSWildcard; aoqi@0: import com.sun.xml.internal.xsom.XSXPath; aoqi@0: import com.sun.xml.internal.xsom.visitor.XSSimpleTypeVisitor; aoqi@0: import com.sun.xml.internal.xsom.visitor.XSVisitor; aoqi@0: aoqi@0: /** aoqi@0: * Reports all unacknowledged customizations as errors. aoqi@0: * aoqi@0: *

aoqi@0: * Since we scan the whole content tree, we use this to check for unused aoqi@0: * xmime:expectedContentTypes attributes. TODO: if we find this kind of error checks more aoqi@0: * common, use the visitors so that we don't have to mix everything in one class. aoqi@0: * aoqi@0: * @author aoqi@0: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) aoqi@0: */ aoqi@0: class UnusedCustomizationChecker extends BindingComponent implements XSVisitor, XSSimpleTypeVisitor { aoqi@0: private final BGMBuilder builder = Ring.get(BGMBuilder.class); aoqi@0: private final SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class); aoqi@0: aoqi@0: private final Set visitedComponents = new HashSet(); aoqi@0: aoqi@0: /** aoqi@0: * Runs the check. aoqi@0: */ aoqi@0: void run() { aoqi@0: for( XSSchema s : Ring.get(XSSchemaSet.class).getSchemas() ) { aoqi@0: schema(s); aoqi@0: run( s.getAttGroupDecls() ); aoqi@0: run( s.getAttributeDecls() ); aoqi@0: run( s.getComplexTypes() ); aoqi@0: run( s.getElementDecls() ); aoqi@0: run( s.getModelGroupDecls() ); aoqi@0: run( s.getNotations() ); aoqi@0: run( s.getSimpleTypes() ); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void run( Map col ) { aoqi@0: for( XSComponent c : col.values() ) aoqi@0: c.visit(this); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Checks unused customizations on this component aoqi@0: * and returns true if this is the first time this aoqi@0: * component is checked. aoqi@0: */ aoqi@0: private boolean check( XSComponent c ) { aoqi@0: if( !visitedComponents.add(c) ) aoqi@0: return false; // already processed aoqi@0: aoqi@0: for( BIDeclaration decl : builder.getBindInfo(c).getDecls() ) aoqi@0: check(decl, c); aoqi@0: aoqi@0: checkExpectedContentTypes(c); aoqi@0: aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: private void checkExpectedContentTypes(XSComponent c) { aoqi@0: if(c.getForeignAttribute(WellKnownNamespace.XML_MIME_URI, Const.EXPECTED_CONTENT_TYPES)==null) aoqi@0: return; // no such attribute aoqi@0: if(c instanceof XSParticle) aoqi@0: return; // particles get the same foreign attributes as local element decls, aoqi@0: // so we need to skip them aoqi@0: aoqi@0: if(!stb.isAcknowledgedXmimeContentTypes(c)) { aoqi@0: // this is not used aoqi@0: getErrorReporter().warning(c.getLocator(),Messages.WARN_UNUSED_EXPECTED_CONTENT_TYPES); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void check(BIDeclaration decl, XSComponent c) { aoqi@0: if( !decl.isAcknowledged() ) { aoqi@0: getErrorReporter().error( aoqi@0: decl.getLocation(), aoqi@0: Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION, aoqi@0: decl.getName().getLocalPart() aoqi@0: ); aoqi@0: getErrorReporter().error( aoqi@0: c.getLocator(), aoqi@0: Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION); aoqi@0: // mark it as acknowledged to avoid aoqi@0: // duplicated error messages. aoqi@0: decl.markAsAcknowledged(); aoqi@0: } aoqi@0: for (BIDeclaration d : decl.getChildren()) aoqi@0: check(d,c); aoqi@0: } aoqi@0: aoqi@0: aoqi@0: public void annotation(XSAnnotation ann) {} aoqi@0: aoqi@0: public void attGroupDecl(XSAttGroupDecl decl) { aoqi@0: if(check(decl)) aoqi@0: attContainer(decl); aoqi@0: } aoqi@0: aoqi@0: public void attributeDecl(XSAttributeDecl decl) { aoqi@0: if(check(decl)) aoqi@0: decl.getType().visit((XSSimpleTypeVisitor)this); aoqi@0: } aoqi@0: aoqi@0: public void attributeUse(XSAttributeUse use) { aoqi@0: if(check(use)) aoqi@0: use.getDecl().visit(this); aoqi@0: } aoqi@0: aoqi@0: public void complexType(XSComplexType type) { aoqi@0: if(check(type)) { aoqi@0: // don't need to check the base type -- it must be global, thus aoqi@0: // it is covered already aoqi@0: type.getContentType().visit(this); aoqi@0: attContainer(type); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void attContainer( XSAttContainer cont ) { aoqi@0: for( Iterator itr = cont.iterateAttGroups(); itr.hasNext(); ) aoqi@0: ((XSAttGroupDecl)itr.next()).visit(this); aoqi@0: aoqi@0: for( Iterator itr = cont.iterateDeclaredAttributeUses(); itr.hasNext(); ) aoqi@0: ((XSAttributeUse)itr.next()).visit(this); aoqi@0: aoqi@0: XSWildcard wc = cont.getAttributeWildcard(); aoqi@0: if(wc!=null) wc.visit(this); aoqi@0: } aoqi@0: aoqi@0: public void schema(XSSchema schema) { aoqi@0: check(schema); aoqi@0: } aoqi@0: aoqi@0: public void facet(XSFacet facet) { aoqi@0: check(facet); aoqi@0: } aoqi@0: aoqi@0: public void notation(XSNotation notation) { aoqi@0: check(notation); aoqi@0: } aoqi@0: aoqi@0: public void wildcard(XSWildcard wc) { aoqi@0: check(wc); aoqi@0: } aoqi@0: aoqi@0: public void modelGroupDecl(XSModelGroupDecl decl) { aoqi@0: if(check(decl)) aoqi@0: decl.getModelGroup().visit(this); aoqi@0: } aoqi@0: aoqi@0: public void modelGroup(XSModelGroup group) { aoqi@0: if(check(group)) { aoqi@0: for( int i=0; i