src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ModelBuilder.java

Fri, 22 Nov 2013 21:11:19 +0100

author
mkos
date
Fri, 22 Nov 2013 21:11:19 +0100
changeset 450
b0c2840e2513
parent 384
8f2986ff0235
child 637
9c07ef4934dd
permissions
-rw-r--r--

8010935: Better XML handling
8027378: Two closed/javax/xml/8005432 fails with jdk7u51b04
8028382: Two javax/xml/8005433 tests still fail after the fix JDK-8028147
Summary: base fix + fixes for test regressions; fix also reviewed by Maxim Soloviev, Alexander Fomin
Reviewed-by: mchung, mgrebac, mullan

ohair@286 1 /*
alanb@368 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
ohair@286 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286 4 *
ohair@286 5 * This code is free software; you can redistribute it and/or modify it
ohair@286 6 * under the terms of the GNU General Public License version 2 only, as
ohair@286 7 * published by the Free Software Foundation. Oracle designates this
ohair@286 8 * particular file as subject to the "Classpath" exception as provided
ohair@286 9 * by Oracle in the LICENSE file that accompanied this code.
ohair@286 10 *
ohair@286 11 * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286 14 * version 2 for more details (a copy is included in the LICENSE file that
ohair@286 15 * accompanied this code).
ohair@286 16 *
ohair@286 17 * You should have received a copy of the GNU General Public License version
ohair@286 18 * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286 20 *
ohair@286 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286 22 * or visit www.oracle.com if you need additional information or have any
ohair@286 23 * questions.
ohair@286 24 */
ohair@286 25
ohair@286 26 package com.sun.xml.internal.bind.v2.model.impl;
ohair@286 27
alanb@368 28 import java.lang.reflect.ParameterizedType;
alanb@368 29 import java.lang.reflect.Type;
ohair@286 30 import java.util.HashMap;
ohair@286 31 import java.util.Map;
alanb@368 32 import java.util.logging.Level;
alanb@368 33 import java.util.logging.Logger;
ohair@286 34
alanb@368 35 import javax.xml.bind.JAXBElement;
ohair@286 36 import javax.xml.bind.annotation.XmlAttachmentRef;
ohair@286 37 import javax.xml.bind.annotation.XmlRegistry;
ohair@286 38 import javax.xml.bind.annotation.XmlSchema;
ohair@286 39 import javax.xml.bind.annotation.XmlSeeAlso;
ohair@286 40 import javax.xml.bind.annotation.XmlTransient;
ohair@286 41 import javax.xml.namespace.QName;
ohair@286 42
ohair@286 43 import com.sun.xml.internal.bind.util.Which;
ohair@286 44 import com.sun.xml.internal.bind.v2.model.annotation.AnnotationReader;
ohair@286 45 import com.sun.xml.internal.bind.v2.model.annotation.ClassLocatable;
ohair@286 46 import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
ohair@286 47 import com.sun.xml.internal.bind.v2.model.core.ClassInfo;
ohair@286 48 import com.sun.xml.internal.bind.v2.model.core.ErrorHandler;
ohair@286 49 import com.sun.xml.internal.bind.v2.model.core.LeafInfo;
ohair@286 50 import com.sun.xml.internal.bind.v2.model.core.NonElement;
ohair@286 51 import com.sun.xml.internal.bind.v2.model.core.PropertyInfo;
ohair@286 52 import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
ohair@286 53 import com.sun.xml.internal.bind.v2.model.core.Ref;
ohair@286 54 import com.sun.xml.internal.bind.v2.model.core.RegistryInfo;
ohair@286 55 import com.sun.xml.internal.bind.v2.model.core.TypeInfo;
ohair@286 56 import com.sun.xml.internal.bind.v2.model.core.TypeInfoSet;
ohair@286 57 import com.sun.xml.internal.bind.v2.model.nav.Navigator;
alanb@368 58 import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
ohair@286 59 import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationException;
ohair@286 60 import com.sun.xml.internal.bind.WhiteSpaceProcessor;
ohair@286 61
ohair@286 62 /**
ohair@286 63 * Builds a {@link TypeInfoSet} (a set of JAXB properties)
ohair@286 64 * by using {@link ElementInfoImpl} and {@link ClassInfoImpl}.
ohair@286 65 * from annotated Java classes.
ohair@286 66 *
ohair@286 67 * <p>
ohair@286 68 * This class uses {@link Navigator} and {@link AnnotationReader} to
ohair@286 69 * work with arbitrary annotation source and arbitrary Java model.
ohair@286 70 * For this purpose this class is parameterized.
ohair@286 71 *
ohair@286 72 * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
ohair@286 73 */
alanb@368 74 public class ModelBuilder<T,C,F,M> implements ModelBuilderI<T,C,F,M> {
alanb@368 75 private static final Logger logger;
ohair@286 76
ohair@286 77 /**
ohair@286 78 * {@link TypeInfo}s that are built will go into this set.
ohair@286 79 */
ohair@286 80 final TypeInfoSetImpl<T,C,F,M> typeInfoSet;
ohair@286 81
ohair@286 82 public final AnnotationReader<T,C,F,M> reader;
ohair@286 83
ohair@286 84 public final Navigator<T,C,F,M> nav;
ohair@286 85
ohair@286 86 /**
ohair@286 87 * Used to detect collisions among global type names.
ohair@286 88 */
ohair@286 89 private final Map<QName,TypeInfo> typeNames = new HashMap<QName,TypeInfo>();
ohair@286 90
ohair@286 91 /**
ohair@286 92 * JAXB doesn't want to use namespaces unless we are told to, but WS-I BP
ohair@286 93 * conformace requires JAX-RPC to always use a non-empty namespace URI.
ohair@286 94 * (see http://www.ws-i.org/Profiles/BasicProfile-1.0-2004-04-16.html#WSDLTYPES R2105)
ohair@286 95 *
ohair@286 96 * <p>
ohair@286 97 * To work around this issue, we allow the use of the empty namespaces to be
ohair@286 98 * replaced by a particular designated namespace URI.
ohair@286 99 *
ohair@286 100 * <p>
ohair@286 101 * This field keeps the value of that replacing namespace URI.
ohair@286 102 * When there's no replacement, this field is set to "".
ohair@286 103 */
ohair@286 104 public final String defaultNsUri;
ohair@286 105
ohair@286 106
ohair@286 107 /**
ohair@286 108 * Packages whose registries are already added.
ohair@286 109 */
ohair@286 110 /*package*/ final Map<String,RegistryInfoImpl<T,C,F,M>> registries
ohair@286 111 = new HashMap<String,RegistryInfoImpl<T,C,F,M>>();
ohair@286 112
ohair@286 113 private final Map<C,C> subclassReplacements;
ohair@286 114
ohair@286 115 /**
ohair@286 116 * @see #setErrorHandler
ohair@286 117 */
ohair@286 118 private ErrorHandler errorHandler;
ohair@286 119 private boolean hadError;
ohair@286 120
ohair@286 121 /**
ohair@286 122 * Set to true if the model includes {@link XmlAttachmentRef}. JAX-WS
ohair@286 123 * needs to know this information.
ohair@286 124 */
ohair@286 125 public boolean hasSwaRef;
ohair@286 126
ohair@286 127 private final ErrorHandler proxyErrorHandler = new ErrorHandler() {
ohair@286 128 public void error(IllegalAnnotationException e) {
ohair@286 129 reportError(e);
ohair@286 130 }
ohair@286 131 };
ohair@286 132
ohair@286 133 public ModelBuilder(
ohair@286 134 AnnotationReader<T, C, F, M> reader,
ohair@286 135 Navigator<T, C, F, M> navigator,
ohair@286 136 Map<C, C> subclassReplacements,
ohair@286 137 String defaultNamespaceRemap
ohair@286 138 ) {
ohair@286 139
ohair@286 140 this.reader = reader;
ohair@286 141 this.nav = navigator;
ohair@286 142 this.subclassReplacements = subclassReplacements;
ohair@286 143 if(defaultNamespaceRemap==null)
ohair@286 144 defaultNamespaceRemap = "";
ohair@286 145 this.defaultNsUri = defaultNamespaceRemap;
ohair@286 146 reader.setErrorHandler(proxyErrorHandler);
ohair@286 147 typeInfoSet = createTypeInfoSet();
ohair@286 148 }
ohair@286 149
ohair@286 150 /**
ohair@286 151 * Makes sure that we are running with 2.1 JAXB API,
ohair@286 152 * and report an error if not.
ohair@286 153 */
ohair@286 154 static {
ohair@286 155 try {
ohair@286 156 XmlSchema s = null;
ohair@286 157 s.location();
ohair@286 158 } catch (NullPointerException e) {
ohair@286 159 // as epxected
ohair@286 160 } catch (NoSuchMethodError e) {
ohair@286 161 // this is not a 2.1 API. Where is it being loaded from?
ohair@286 162 Messages res;
ohair@286 163 if (SecureLoader.getClassClassLoader(XmlSchema.class) == null) {
ohair@286 164 res = Messages.INCOMPATIBLE_API_VERSION_MUSTANG;
ohair@286 165 } else {
ohair@286 166 res = Messages.INCOMPATIBLE_API_VERSION;
ohair@286 167 }
ohair@286 168
ohair@286 169 throw new LinkageError( res.format(
ohair@286 170 Which.which(XmlSchema.class),
ohair@286 171 Which.which(ModelBuilder.class)
ohair@286 172 ));
ohair@286 173 }
ohair@286 174 }
ohair@286 175
ohair@286 176 /**
ohair@286 177 * Makes sure that we don't have conflicting 1.0 runtime,
ohair@286 178 * and report an error if we do.
ohair@286 179 */
ohair@286 180 static {
ohair@286 181 try {
ohair@286 182 WhiteSpaceProcessor.isWhiteSpace("xyz");
ohair@286 183 } catch (NoSuchMethodError e) {
ohair@286 184 // we seem to be getting 1.0 runtime
ohair@286 185 throw new LinkageError( Messages.RUNNING_WITH_1_0_RUNTIME.format(
ohair@286 186 Which.which(WhiteSpaceProcessor.class),
ohair@286 187 Which.which(ModelBuilder.class)
ohair@286 188 ));
ohair@286 189 }
ohair@286 190 }
ohair@286 191
alanb@368 192 /**
alanb@368 193 * Logger init
alanb@368 194 */
alanb@368 195 static {
alanb@368 196 logger = Logger.getLogger(ModelBuilder.class.getName());
alanb@368 197 }
alanb@368 198
ohair@286 199 protected TypeInfoSetImpl<T,C,F,M> createTypeInfoSet() {
ohair@286 200 return new TypeInfoSetImpl<T,C,F,M>(nav,reader,BuiltinLeafInfoImpl.createLeaves(nav));
ohair@286 201 }
ohair@286 202
ohair@286 203 /**
ohair@286 204 * Builds a JAXB {@link ClassInfo} model from a given class declaration
ohair@286 205 * and adds that to this model owner.
ohair@286 206 *
ohair@286 207 * <p>
ohair@286 208 * Return type is either {@link ClassInfo} or {@link LeafInfo} (for types like
ohair@286 209 * {@link String} or {@link Enum}-derived ones)
ohair@286 210 */
ohair@286 211 public NonElement<T,C> getClassInfo( C clazz, Locatable upstream ) {
ohair@286 212 return getClassInfo(clazz,false,upstream);
ohair@286 213 }
ohair@286 214
ohair@286 215 /**
ohair@286 216 * For limited cases where the caller needs to search for a super class.
ohair@286 217 * This is necessary because we don't want {@link #subclassReplacements}
ohair@286 218 * to kick in for the super class search, which will cause infinite recursion.
ohair@286 219 */
ohair@286 220 public NonElement<T,C> getClassInfo( C clazz, boolean searchForSuperClass, Locatable upstream ) {
ohair@286 221 assert clazz!=null;
ohair@286 222 NonElement<T,C> r = typeInfoSet.getClassInfo(clazz);
ohair@286 223 if(r!=null)
ohair@286 224 return r;
ohair@286 225
ohair@286 226 if(nav.isEnum(clazz)) {
ohair@286 227 EnumLeafInfoImpl<T,C,F,M> li = createEnumLeafInfo(clazz,upstream);
ohair@286 228 typeInfoSet.add(li);
ohair@286 229 r = li;
ohair@286 230 addTypeName(r);
ohair@286 231 } else {
ohair@286 232 boolean isReplaced = subclassReplacements.containsKey(clazz);
ohair@286 233 if(isReplaced && !searchForSuperClass) {
ohair@286 234 // handle it as if the replacement was specified
ohair@286 235 r = getClassInfo(subclassReplacements.get(clazz),upstream);
ohair@286 236 } else
ohair@286 237 if(reader.hasClassAnnotation(clazz,XmlTransient.class) || isReplaced) {
ohair@286 238 // handle it as if the base class was specified
ohair@286 239 r = getClassInfo( nav.getSuperClass(clazz), searchForSuperClass,
ohair@286 240 new ClassLocatable<C>(upstream,clazz,nav) );
ohair@286 241 } else {
ohair@286 242 ClassInfoImpl<T,C,F,M> ci = createClassInfo(clazz,upstream);
ohair@286 243 typeInfoSet.add(ci);
ohair@286 244
ohair@286 245 // compute the closure by eagerly expanding references
ohair@286 246 for( PropertyInfo<T,C> p : ci.getProperties() ) {
ohair@286 247 if(p.kind()== PropertyKind.REFERENCE) {
ohair@286 248 // make sure that we have a registry for this package
alanb@368 249 addToRegistry(clazz, (Locatable) p);
alanb@368 250 Class[] prmzdClasses = getParametrizedTypes(p);
alanb@368 251 if (prmzdClasses != null) {
alanb@368 252 for (Class prmzdClass : prmzdClasses) {
alanb@368 253 if (prmzdClass != clazz) {
alanb@368 254 addToRegistry((C) prmzdClass, (Locatable) p);
alanb@368 255 }
alanb@368 256 }
ohair@286 257 }
ohair@286 258 }
ohair@286 259
ohair@286 260 for( TypeInfo<T,C> t : p.ref() )
ohair@286 261 ; // just compute a reference should be suffice
ohair@286 262 }
ohair@286 263 ci.getBaseClass(); // same as above.
ohair@286 264
ohair@286 265 r = ci;
ohair@286 266 addTypeName(r);
ohair@286 267 }
ohair@286 268 }
ohair@286 269
ohair@286 270
ohair@286 271 // more reference closure expansion. @XmlSeeAlso
ohair@286 272 XmlSeeAlso sa = reader.getClassAnnotation(XmlSeeAlso.class, clazz, upstream);
ohair@286 273 if(sa!=null) {
ohair@286 274 for( T t : reader.getClassArrayValue(sa,"value") ) {
ohair@286 275 getTypeInfo(t,(Locatable)sa);
ohair@286 276 }
ohair@286 277 }
ohair@286 278
ohair@286 279
ohair@286 280 return r;
ohair@286 281 }
ohair@286 282
ohair@286 283 /**
alanb@368 284 * Adding package's ObjectFactory methods to registry
alanb@368 285 * @param clazz which package will be used
alanb@368 286 * @param p location
alanb@368 287 */
alanb@368 288 private void addToRegistry(C clazz, Locatable p) {
alanb@368 289 String pkg = nav.getPackageName(clazz);
alanb@368 290 if (!registries.containsKey(pkg)) {
alanb@368 291 // insert the package's object factory
mkos@450 292 C c = nav.loadObjectFactory(clazz, pkg);
alanb@368 293 if (c != null)
alanb@368 294 addRegistry(c, p);
alanb@368 295 }
alanb@368 296 }
alanb@368 297
alanb@368 298 /**
alanb@368 299 * Getting parametrized classes of {@code JAXBElement<...>} property
alanb@368 300 * @param p property which parametrized types we will try to get
alanb@368 301 * @return null - if it's not JAXBElement property, or it's not parametrized, and array of parametrized classes in other case
alanb@368 302 */
alanb@368 303 private Class[] getParametrizedTypes(PropertyInfo p) {
alanb@368 304 try {
alanb@368 305 Type pType = ((RuntimePropertyInfo) p).getIndividualType();
alanb@368 306 if (pType instanceof ParameterizedType) {
alanb@368 307 ParameterizedType prmzdType = (ParameterizedType) pType;
alanb@368 308 if (prmzdType.getRawType() == JAXBElement.class) {
alanb@368 309 Type[] actualTypes = prmzdType.getActualTypeArguments();
alanb@368 310 Class[] result = new Class[actualTypes.length];
alanb@368 311 for (int i = 0; i < actualTypes.length; i++) {
alanb@368 312 result[i] = (Class) actualTypes[i];
alanb@368 313 }
alanb@368 314 return result;
alanb@368 315 }
alanb@368 316 }
alanb@368 317 } catch (Exception e) {
alanb@368 318 logger.log(Level.FINE, "Error in ModelBuilder.getParametrizedTypes. " + e.getMessage());
alanb@368 319 }
alanb@368 320 return null;
alanb@368 321 }
alanb@368 322
alanb@368 323 /**
ohair@286 324 * Checks the uniqueness of the type name.
ohair@286 325 */
ohair@286 326 private void addTypeName(NonElement<T, C> r) {
ohair@286 327 QName t = r.getTypeName();
ohair@286 328 if(t==null) return;
ohair@286 329
ohair@286 330 TypeInfo old = typeNames.put(t,r);
ohair@286 331 if(old!=null) {
ohair@286 332 // collision
ohair@286 333 reportError(new IllegalAnnotationException(
ohair@286 334 Messages.CONFLICTING_XML_TYPE_MAPPING.format(r.getTypeName()),
ohair@286 335 old, r ));
ohair@286 336 }
ohair@286 337 }
ohair@286 338
ohair@286 339 /**
ohair@286 340 * Have the builder recognize the type (if it hasn't done so yet),
ohair@286 341 * and returns a {@link NonElement} that represents it.
ohair@286 342 *
ohair@286 343 * @return
ohair@286 344 * always non-null.
ohair@286 345 */
ohair@286 346 public NonElement<T,C> getTypeInfo(T t,Locatable upstream) {
ohair@286 347 NonElement<T,C> r = typeInfoSet.getTypeInfo(t);
ohair@286 348 if(r!=null) return r;
ohair@286 349
ohair@286 350 if(nav.isArray(t)) { // no need for checking byte[], because above typeInfoset.getTypeInfo() would return non-null
ohair@286 351 ArrayInfoImpl<T,C,F,M> ai =
ohair@286 352 createArrayInfo(upstream, t);
ohair@286 353 addTypeName(ai);
ohair@286 354 typeInfoSet.add(ai);
ohair@286 355 return ai;
ohair@286 356 }
ohair@286 357
ohair@286 358 C c = nav.asDecl(t);
ohair@286 359 assert c!=null : t.toString()+" must be a leaf, but we failed to recognize it.";
ohair@286 360 return getClassInfo(c,upstream);
ohair@286 361 }
ohair@286 362
ohair@286 363 /**
ohair@286 364 * This method is used to add a root reference to a model.
ohair@286 365 */
ohair@286 366 public NonElement<T,C> getTypeInfo(Ref<T,C> ref) {
ohair@286 367 // TODO: handle XmlValueList
ohair@286 368 assert !ref.valueList;
ohair@286 369 C c = nav.asDecl(ref.type);
ohair@286 370 if(c!=null && reader.getClassAnnotation(XmlRegistry.class,c,null/*TODO: is this right?*/)!=null) {
ohair@286 371 if(!registries.containsKey(nav.getPackageName(c)))
ohair@286 372 addRegistry(c,null);
ohair@286 373 return null; // TODO: is this correct?
ohair@286 374 } else
ohair@286 375 return getTypeInfo(ref.type,null);
ohair@286 376 }
ohair@286 377
ohair@286 378
ohair@286 379 protected EnumLeafInfoImpl<T,C,F,M> createEnumLeafInfo(C clazz,Locatable upstream) {
ohair@286 380 return new EnumLeafInfoImpl<T,C,F,M>(this,upstream,clazz,nav.use(clazz));
ohair@286 381 }
ohair@286 382
ohair@286 383 protected ClassInfoImpl<T,C,F,M> createClassInfo(C clazz, Locatable upstream ) {
ohair@286 384 return new ClassInfoImpl<T,C,F,M>(this,upstream,clazz);
ohair@286 385 }
ohair@286 386
ohair@286 387 protected ElementInfoImpl<T,C,F,M> createElementInfo(
ohair@286 388 RegistryInfoImpl<T,C,F,M> registryInfo, M m) throws IllegalAnnotationException {
ohair@286 389 return new ElementInfoImpl<T,C,F,M>(this,registryInfo,m);
ohair@286 390 }
ohair@286 391
ohair@286 392 protected ArrayInfoImpl<T,C,F,M> createArrayInfo(Locatable upstream, T arrayType) {
ohair@286 393 return new ArrayInfoImpl<T, C, F, M>(this,upstream,arrayType);
ohair@286 394 }
ohair@286 395
ohair@286 396
ohair@286 397 /**
ohair@286 398 * Visits a class with {@link XmlRegistry} and records all the element mappings
ohair@286 399 * in it.
ohair@286 400 */
ohair@286 401 public RegistryInfo<T,C> addRegistry(C registryClass, Locatable upstream ) {
ohair@286 402 return new RegistryInfoImpl<T,C,F,M>(this,upstream,registryClass);
ohair@286 403 }
ohair@286 404
ohair@286 405 /**
ohair@286 406 * Gets a {@link RegistryInfo} for the given package.
ohair@286 407 *
ohair@286 408 * @return
ohair@286 409 * null if no registry exists for the package.
ohair@286 410 * unlike other getXXX methods on this class,
ohair@286 411 * this method is side-effect free.
ohair@286 412 */
ohair@286 413 public RegistryInfo<T,C> getRegistry(String packageName) {
ohair@286 414 return registries.get(packageName);
ohair@286 415 }
ohair@286 416
ohair@286 417 private boolean linked;
ohair@286 418
ohair@286 419 /**
ohair@286 420 * Called after all the classes are added to the type set
ohair@286 421 * to "link" them together.
ohair@286 422 *
ohair@286 423 * <p>
ohair@286 424 * Don't expose implementation classes in the signature.
ohair@286 425 *
ohair@286 426 * @return
ohair@286 427 * fully built {@link TypeInfoSet} that represents the model,
ohair@286 428 * or null if there was an error.
ohair@286 429 */
ohair@286 430 public TypeInfoSet<T,C,F,M> link() {
ohair@286 431
ohair@286 432 assert !linked;
ohair@286 433 linked = true;
ohair@286 434
ohair@286 435 for( ElementInfoImpl ei : typeInfoSet.getAllElements() )
ohair@286 436 ei.link();
ohair@286 437
ohair@286 438 for( ClassInfoImpl ci : typeInfoSet.beans().values() )
ohair@286 439 ci.link();
ohair@286 440
ohair@286 441 for( EnumLeafInfoImpl li : typeInfoSet.enums().values() )
ohair@286 442 li.link();
ohair@286 443
ohair@286 444 if(hadError)
ohair@286 445 return null;
ohair@286 446 else
ohair@286 447 return typeInfoSet;
ohair@286 448 }
ohair@286 449
ohair@286 450 //
ohair@286 451 //
ohair@286 452 // error handling
ohair@286 453 //
ohair@286 454 //
ohair@286 455
ohair@286 456 /**
ohair@286 457 * Sets the error handler that receives errors discovered during the model building.
ohair@286 458 *
ohair@286 459 * @param errorHandler
ohair@286 460 * can be null.
ohair@286 461 */
ohair@286 462 public void setErrorHandler(ErrorHandler errorHandler) {
ohair@286 463 this.errorHandler = errorHandler;
ohair@286 464 }
ohair@286 465
ohair@286 466 public final void reportError(IllegalAnnotationException e) {
ohair@286 467 hadError = true;
ohair@286 468 if(errorHandler!=null)
ohair@286 469 errorHandler.error(e);
ohair@286 470 }
ohair@286 471
ohair@286 472 public boolean isReplaced(C sc) {
ohair@286 473 return subclassReplacements.containsKey(sc);
ohair@286 474 }
alanb@368 475
alanb@368 476 @Override
alanb@368 477 public Navigator<T, C, F, M> getNavigator() {
alanb@368 478 return nav;
alanb@368 479 }
alanb@368 480
alanb@368 481 @Override
alanb@368 482 public AnnotationReader<T, C, F, M> getReader() {
alanb@368 483 return reader;
alanb@368 484 }
ohair@286 485 }

mercurial