public Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
    if (loader == null) {
      // these variables have to be set before they are initialized,
      // because the initialization may build other loaders and they may refer to this.
      StructureLoader sl = new StructureLoader(this);
      loader = sl;
      if (ci.hasSubClasses()) loaderWithTypeSubst = new XsiTypeLoader(this);
      else
        // optimization. we know there can be no @xsi:type
        loaderWithTypeSubst = loader;

      sl.init(context, this, ci.getAttributeWildcard());
    }
    if (typeSubstitutionCapable) return loaderWithTypeSubst;
    else return loader;
  }
  /*package*/ ClassBeanInfoImpl(JAXBContextImpl owner, RuntimeClassInfo ci) {
    super(owner, ci, ci.getClazz(), ci.getTypeName(), ci.isElement(), false, true);

    this.ci = ci;
    this.inheritedAttWildcard = ci.getAttributeWildcard();
    this.xducer = ci.getTransducer();
    this.factoryMethod = ci.getFactoryMethod();
    this.retainPropertyInfo = owner.retainPropertyInfo;

    // make the factory accessible
    if (factoryMethod != null) {
      int classMod = factoryMethod.getDeclaringClass().getModifiers();

      if (!Modifier.isPublic(classMod) || !Modifier.isPublic(factoryMethod.getModifiers())) {
        // attempt to make it work even if the constructor is not accessible
        try {
          factoryMethod.setAccessible(true);
        } catch (SecurityException e) {
          // but if we don't have a permission to do so, work gracefully.
          logger.log(
              Level.FINE, "Unable to make the method of " + factoryMethod + " accessible", e);
          throw e;
        }
      }
    }

    if (ci.getBaseClass() == null) this.superClazz = null;
    else this.superClazz = owner.getOrCreate(ci.getBaseClass());

    if (superClazz != null && superClazz.xmlLocatorField != null)
      xmlLocatorField = superClazz.xmlLocatorField;
    else xmlLocatorField = ci.getLocatorField();

    // create property objects
    Collection<? extends RuntimePropertyInfo> ps = ci.getProperties();
    this.properties = new Property[ps.size()];
    int idx = 0;
    boolean elementOnly = true;
    for (RuntimePropertyInfo info : ps) {
      Property p = PropertyFactory.create(owner, info);
      if (info.id() == ID.ID) idProperty = p;
      properties[idx++] = p;
      elementOnly &= info.elementOnlyContent();
      checkOverrideProperties(p);
    }
    // super class' idProperty might not be computed at this point,
    // so check that later

    hasElementOnlyContentModel(elementOnly);
    // again update this value later when we know that of the super class

    if (ci.isElement()) tagName = owner.nameBuilder.createElementName(ci.getElementName());
    else tagName = null;

    setLifecycleFlags();
  }