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

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 450
b0c2840e2513
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

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

mercurial