1 /* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.tools.internal.xjc.reader.xmlschema; 27 28 import java.util.HashSet; 29 import java.util.Iterator; 30 import java.util.Map; 31 import java.util.Set; 32 33 import com.sun.tools.internal.xjc.reader.Const; 34 import com.sun.tools.internal.xjc.reader.Ring; 35 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration; 36 import com.sun.xml.internal.bind.v2.WellKnownNamespace; 37 import com.sun.xml.internal.xsom.XSAnnotation; 38 import com.sun.xml.internal.xsom.XSAttContainer; 39 import com.sun.xml.internal.xsom.XSAttGroupDecl; 40 import com.sun.xml.internal.xsom.XSAttributeDecl; 41 import com.sun.xml.internal.xsom.XSAttributeUse; 42 import com.sun.xml.internal.xsom.XSComplexType; 43 import com.sun.xml.internal.xsom.XSComponent; 44 import com.sun.xml.internal.xsom.XSContentType; 45 import com.sun.xml.internal.xsom.XSElementDecl; 46 import com.sun.xml.internal.xsom.XSFacet; 47 import com.sun.xml.internal.xsom.XSIdentityConstraint; 48 import com.sun.xml.internal.xsom.XSListSimpleType; 49 import com.sun.xml.internal.xsom.XSModelGroup; 50 import com.sun.xml.internal.xsom.XSModelGroupDecl; 51 import com.sun.xml.internal.xsom.XSNotation; 52 import com.sun.xml.internal.xsom.XSParticle; 53 import com.sun.xml.internal.xsom.XSRestrictionSimpleType; 54 import com.sun.xml.internal.xsom.XSSchema; 55 import com.sun.xml.internal.xsom.XSSchemaSet; 56 import com.sun.xml.internal.xsom.XSSimpleType; 57 import com.sun.xml.internal.xsom.XSUnionSimpleType; 58 import com.sun.xml.internal.xsom.XSWildcard; 59 import com.sun.xml.internal.xsom.XSXPath; 60 import com.sun.xml.internal.xsom.visitor.XSSimpleTypeVisitor; 61 import com.sun.xml.internal.xsom.visitor.XSVisitor; 62 63 /** 64 * Reports all unacknowledged customizations as errors. 65 * 66 * <p> 67 * Since we scan the whole content tree, we use this to check for unused 68 * {@code xmime:expectedContentTypes} attributes. 69 * TODO: if we find this kind of error checks more 70 * common, use the visitors so that we don't have to mix everything in one class. 71 * 72 * @author 73 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 74 */ 75 class UnusedCustomizationChecker extends BindingComponent implements XSVisitor, XSSimpleTypeVisitor { 76 private final BGMBuilder builder = Ring.get(BGMBuilder.class); 77 private final SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class); 78 79 private final Set<XSComponent> visitedComponents = new HashSet<XSComponent>(); 80 81 /** 82 * Runs the check. 83 */ 84 void run() { 85 for( XSSchema s : Ring.get(XSSchemaSet.class).getSchemas() ) { 86 schema(s); 87 run( s.getAttGroupDecls() ); 88 run( s.getAttributeDecls() ); 89 run( s.getComplexTypes() ); 90 run( s.getElementDecls() ); 91 run( s.getModelGroupDecls() ); 92 run( s.getNotations() ); 93 run( s.getSimpleTypes() ); 94 } 95 } 96 97 private void run( Map<String,? extends XSComponent> col ) { 98 for( XSComponent c : col.values() ) 99 c.visit(this); 100 } 101 102 103 /** 104 * Checks unused customizations on this component 105 * and returns true if this is the first time this 106 * component is checked. 107 */ 108 private boolean check( XSComponent c ) { 109 if( !visitedComponents.add(c) ) 110 return false; // already processed 111 112 for( BIDeclaration decl : builder.getBindInfo(c).getDecls() ) 113 check(decl, c); 114 115 checkExpectedContentTypes(c); 116 117 return true; 118 } 119 120 private void checkExpectedContentTypes(XSComponent c) { 121 if(c.getForeignAttribute(WellKnownNamespace.XML_MIME_URI, Const.EXPECTED_CONTENT_TYPES)==null) 122 return; // no such attribute 123 if(c instanceof XSParticle) 124 return; // particles get the same foreign attributes as local element decls, 125 // so we need to skip them 126 127 if(!stb.isAcknowledgedXmimeContentTypes(c)) { 128 // this is not used 129 getErrorReporter().warning(c.getLocator(),Messages.WARN_UNUSED_EXPECTED_CONTENT_TYPES); 130 } 131 } 132 133 private void check(BIDeclaration decl, XSComponent c) { 134 if( !decl.isAcknowledged() ) { 135 getErrorReporter().error( 136 decl.getLocation(), 137 Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION, 138 decl.getName().getLocalPart() 139 ); 140 getErrorReporter().error( 141 c.getLocator(), 142 Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION); 143 // mark it as acknowledged to avoid 144 // duplicated error messages. 145 decl.markAsAcknowledged(); 146 } 147 for (BIDeclaration d : decl.getChildren()) 148 check(d,c); 149 } 150 151 152 public void annotation(XSAnnotation ann) {} 153 154 public void attGroupDecl(XSAttGroupDecl decl) { 155 if(check(decl)) 156 attContainer(decl); 157 } 158 159 public void attributeDecl(XSAttributeDecl decl) { 160 if(check(decl)) 161 decl.getType().visit((XSSimpleTypeVisitor)this); 162 } 163 164 public void attributeUse(XSAttributeUse use) { 165 if(check(use)) 166 use.getDecl().visit(this); 167 } 168 169 public void complexType(XSComplexType type) { 170 if(check(type)) { 171 // don't need to check the base type -- it must be global, thus 172 // it is covered already 173 type.getContentType().visit(this); 174 attContainer(type); 175 } 176 } 177 178 private void attContainer( XSAttContainer cont ) { 179 for( Iterator itr = cont.iterateAttGroups(); itr.hasNext(); ) 180 ((XSAttGroupDecl)itr.next()).visit(this); 181 182 for( Iterator itr = cont.iterateDeclaredAttributeUses(); itr.hasNext(); ) 183 ((XSAttributeUse)itr.next()).visit(this); 184 185 XSWildcard wc = cont.getAttributeWildcard(); 186 if(wc!=null) wc.visit(this); 187 } 188 189 public void schema(XSSchema schema) { 190 check(schema); 191 } 192 193 public void facet(XSFacet facet) { 194 check(facet); 195 } 196 197 public void notation(XSNotation notation) { 198 check(notation); 199 } 200 201 public void wildcard(XSWildcard wc) { 202 check(wc); 203 } 204 205 public void modelGroupDecl(XSModelGroupDecl decl) { 206 if(check(decl)) 207 decl.getModelGroup().visit(this); 208 } 209 210 public void modelGroup(XSModelGroup group) { 211 if(check(group)) { 212 for( int i=0; i<group.getSize(); i++ ) 213 group.getChild(i).visit(this); 214 } 215 } 216 217 public void elementDecl(XSElementDecl decl) { 218 if(check(decl)) { 219 decl.getType().visit(this); 220 for( XSIdentityConstraint id : decl.getIdentityConstraints() ) 221 id.visit(this); 222 } 223 } 224 225 public void simpleType(XSSimpleType simpleType) { 226 if(check(simpleType)) 227 simpleType.visit( (XSSimpleTypeVisitor)this ); 228 } 229 230 public void particle(XSParticle particle) { 231 if(check(particle)) 232 particle.getTerm().visit(this); 233 } 234 235 public void empty(XSContentType empty) { 236 check(empty); 237 } 238 239 public void listSimpleType(XSListSimpleType type) { 240 if(check(type)) 241 type.getItemType().visit((XSSimpleTypeVisitor)this); 242 } 243 244 public void restrictionSimpleType(XSRestrictionSimpleType type) { 245 if(check(type)) 246 type.getBaseType().visit(this); 247 } 248 249 public void unionSimpleType(XSUnionSimpleType type) { 250 if(check(type)) { 251 for( int i=0; i<type.getMemberSize(); i++ ) 252 type.getMember(i).visit((XSSimpleTypeVisitor)this); 253 } 254 } 255 256 public void identityConstraint(XSIdentityConstraint id) { 257 if(check(id)) { 258 id.getSelector().visit(this); 259 for( XSXPath xp : id.getFields() ) 260 xp.visit(this); 261 } 262 } 263 264 public void xpath(XSXPath xp) { 265 check(xp); 266 } 267 268 }