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 * <tt>xmime:expectedContentTypes</tt> attributes. TODO: if we find this kind of error checks more 69 * common, use the visitors so that we don't have to mix everything in one class. 70 * 71 * @author 72 * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) 73 */ 74 class UnusedCustomizationChecker extends BindingComponent implements XSVisitor, XSSimpleTypeVisitor { 75 private final BGMBuilder builder = Ring.get(BGMBuilder.class); 76 private final SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class); 77 78 private final Set<XSComponent> visitedComponents = new HashSet<XSComponent>(); 79 80 /** 81 * Runs the check. 82 */ 83 void run() { 84 for( XSSchema s : Ring.get(XSSchemaSet.class).getSchemas() ) { 85 schema(s); 86 run( s.getAttGroupDecls() ); 87 run( s.getAttributeDecls() ); 88 run( s.getComplexTypes() ); 89 run( s.getElementDecls() ); 90 run( s.getModelGroupDecls() ); 91 run( s.getNotations() ); 92 run( s.getSimpleTypes() ); 93 } 94 } 95 96 private void run( Map<String,? extends XSComponent> col ) { 97 for( XSComponent c : col.values() ) 98 c.visit(this); 99 } 100 101 102 /** 103 * Checks unused customizations on this component 104 * and returns true if this is the first time this 105 * component is checked. 106 */ 107 private boolean check( XSComponent c ) { 108 if( !visitedComponents.add(c) ) 109 return false; // already processed 110 111 for( BIDeclaration decl : builder.getBindInfo(c).getDecls() ) 112 check(decl, c); 113 114 checkExpectedContentTypes(c); 115 116 return true; 117 } 118 119 private void checkExpectedContentTypes(XSComponent c) { 120 if(c.getForeignAttribute(WellKnownNamespace.XML_MIME_URI, Const.EXPECTED_CONTENT_TYPES)==null) 121 return; // no such attribute 122 if(c instanceof XSParticle) 123 return; // particles get the same foreign attributes as local element decls, 124 // so we need to skip them 125 126 if(!stb.isAcknowledgedXmimeContentTypes(c)) { 127 // this is not used 128 getErrorReporter().warning(c.getLocator(),Messages.WARN_UNUSED_EXPECTED_CONTENT_TYPES); 129 } 130 } 131 132 private void check(BIDeclaration decl, XSComponent c) { 133 if( !decl.isAcknowledged() ) { 134 getErrorReporter().error( 135 decl.getLocation(), 136 Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION, 137 decl.getName().getLocalPart() 138 ); 139 getErrorReporter().error( 140 c.getLocator(), 141 Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION); 142 // mark it as acknowledged to avoid 143 // duplicated error messages. 144 decl.markAsAcknowledged(); 145 } 146 for (BIDeclaration d : decl.getChildren()) 147 check(d,c); 148 } 149 150 151 public void annotation(XSAnnotation ann) {} 152 153 public void attGroupDecl(XSAttGroupDecl decl) { 154 if(check(decl)) 155 attContainer(decl); 156 } 157 158 public void attributeDecl(XSAttributeDecl decl) { 159 if(check(decl)) 160 decl.getType().visit((XSSimpleTypeVisitor)this); 161 } 162 163 public void attributeUse(XSAttributeUse use) { 164 if(check(use)) 165 use.getDecl().visit(this); 166 } 167 168 public void complexType(XSComplexType type) { 169 if(check(type)) { 170 // don't need to check the base type -- it must be global, thus 171 // it is covered already 172 type.getContentType().visit(this); 173 attContainer(type); 174 } 175 } 176 177 private void attContainer( XSAttContainer cont ) { 178 for( Iterator itr = cont.iterateAttGroups(); itr.hasNext(); ) 179 ((XSAttGroupDecl)itr.next()).visit(this); 180 181 for( Iterator itr = cont.iterateDeclaredAttributeUses(); itr.hasNext(); ) 182 ((XSAttributeUse)itr.next()).visit(this); 183 184 XSWildcard wc = cont.getAttributeWildcard(); 185 if(wc!=null) wc.visit(this); 186 } 187 188 public void schema(XSSchema schema) { 189 check(schema); 190 } 191 192 public void facet(XSFacet facet) { 193 check(facet); 194 } 195 196 public void notation(XSNotation notation) { 197 check(notation); 198 } 199 200 public void wildcard(XSWildcard wc) { 201 check(wc); 202 } 203 204 public void modelGroupDecl(XSModelGroupDecl decl) { 205 if(check(decl)) 206 decl.getModelGroup().visit(this); 207 } 208 209 public void modelGroup(XSModelGroup group) { 210 if(check(group)) { 211 for( int i=0; i<group.getSize(); i++ ) 212 group.getChild(i).visit(this); 213 } 214 } 215 216 public void elementDecl(XSElementDecl decl) { 217 if(check(decl)) { 218 decl.getType().visit(this); 219 for( XSIdentityConstraint id : decl.getIdentityConstraints() ) 220 id.visit(this); 221 } 222 } 223 224 public void simpleType(XSSimpleType simpleType) { 225 if(check(simpleType)) 226 simpleType.visit( (XSSimpleTypeVisitor)this ); 227 } 228 229 public void particle(XSParticle particle) { 230 if(check(particle)) 231 particle.getTerm().visit(this); 232 } 233 234 public void empty(XSContentType empty) { 235 check(empty); 236 } 237 238 public void listSimpleType(XSListSimpleType type) { 239 if(check(type)) 240 type.getItemType().visit((XSSimpleTypeVisitor)this); 241 } 242 243 public void restrictionSimpleType(XSRestrictionSimpleType type) { 244 if(check(type)) 245 type.getBaseType().visit(this); 246 } 247 248 public void unionSimpleType(XSUnionSimpleType type) { 249 if(check(type)) { 250 for( int i=0; i<type.getMemberSize(); i++ ) 251 type.getMember(i).visit((XSSimpleTypeVisitor)this); 252 } 253 } 254 255 public void identityConstraint(XSIdentityConstraint id) { 256 if(check(id)) { 257 id.getSelector().visit(this); 258 for( XSXPath xp : id.getFields() ) 259 xp.visit(this); 260 } 261 } 262 263 public void xpath(XSXPath xp) { 264 check(xp); 265 } 266 267 }