Beispiel #1
0
  /** Fill-in the contents of each classes. */
  private void buildContents() {
    ClassSelector cs = getClassSelector();
    SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);

    for (XSSchema s : Ring.get(XSSchemaSet.class).getSchemas()) {
      BISchemaBinding sb = getBindInfo(s).get(BISchemaBinding.class);

      if (sb != null && !sb.map) {
        sb.markAsAcknowledged();
        continue; // no mapping for this package
      }

      getClassSelector()
          .pushClassScope(
              new CClassInfoParent.Package(getClassSelector().getPackage(s.getTargetNamespace())));

      checkMultipleSchemaBindings(s);
      processPackageJavadoc(s);
      populate(s.getAttGroupDecls(), s);
      populate(s.getAttributeDecls(), s);
      populate(s.getElementDecls(), s);
      populate(s.getModelGroupDecls(), s);

      // fill in typeUses
      for (XSType t : s.getTypes().values()) {
        stb.refererStack.push(t);
        model.typeUses().put(getName(t), cs.bindToType(t, s));
        stb.refererStack.pop();
      }

      getClassSelector().popClassScope();
    }
  }
Beispiel #2
0
  private void _build() {
    // do the binding
    buildContents();
    getClassSelector().executeTasks();

    // additional error check
    // Reports unused customizations to the user as errors.
    Ring.get(UnusedCustomizationChecker.class).run();

    Ring.get(ModelChecker.class).check();
  }
Beispiel #3
0
 /** Find all types that refer to the given complex type. */
 public Set<XSComponent> getReferer(XSType c) {
   if (refFinder == null) {
     refFinder = new RefererFinder();
     refFinder.schemaSet(Ring.get(XSSchemaSet.class));
   }
   return refFinder.getReferer(c);
 }
  /** Performs error check */
  public void errorCheck() {
    ErrorReceiver er = Ring.get(ErrorReceiver.class);
    for (QName n : enumBaseTypes) {
      XSSchemaSet xs = Ring.get(XSSchemaSet.class);
      XSSimpleType st = xs.getSimpleType(n.getNamespaceURI(), n.getLocalPart());
      if (st == null) {
        er.error(loc, Messages.ERR_UNDEFINED_SIMPLE_TYPE.format(n));
        continue;
      }

      if (!SimpleTypeBuilder.canBeMappedToTypeSafeEnum(st)) {
        er.error(loc, Messages.ERR_CANNOT_BE_BOUND_TO_SIMPLETYPE.format(n));
        continue;
      }
    }
  }
Beispiel #5
0
  /** List up all the global bindings. */
  private void promoteGlobalBindings() {
    // promote any global bindings in the schema
    XSSchemaSet schemas = Ring.get(XSSchemaSet.class);

    for (XSSchema s : schemas.getSchemas()) {
      BindInfo bi = getBindInfo(s);

      // collect all global customizations
      model.getCustomizations().addAll(bi.toCustomizationList());

      BIGlobalBinding gb = bi.get(BIGlobalBinding.class);
      if (gb == null) continue;

      if (globalBinding == null) {
        globalBinding = gb;
        globalBinding.markAsAcknowledged();
      } else {
        // acknowledge this customization and report an error
        // otherwise the user will see "customization is attached to a wrong place" error,
        // which is incorrect
        gb.markAsAcknowledged();
        getErrorReporter().error(gb.getLocation(), Messages.ERR_MULTIPLE_GLOBAL_BINDINGS);
        getErrorReporter()
            .error(globalBinding.getLocation(), Messages.ERR_MULTIPLE_GLOBAL_BINDINGS_OTHER);
      }
    }

    if (globalBinding == null) {
      // no global customization is present.
      // use the default one
      globalBinding = new BIGlobalBinding();
      BindInfo big = new BindInfo();
      big.addDecl(globalBinding);
      big.setOwner(this, null);
    }

    // code generation mode
    model.strategy = globalBinding.getCodeGenerationStrategy();
    model.rootClass = globalBinding.getSuperClass();
    model.rootInterface = globalBinding.getSuperInterface();

    particleBinder =
        globalBinding.isSimpleMode() ? new ExpressionParticleBinder() : new DefaultParticleBinder();

    // check XJC extensions and realize them
    BISerializable serial = globalBinding.getSerializable();
    if (serial != null) {
      model.serializable = true;
      model.serialVersionUID = serial.uid;
    }

    // obtain the name conversion mode
    if (globalBinding.nameConverter != null) model.setNameConverter(globalBinding.nameConverter);

    // attach global conversions to the appropriate simple types
    globalBinding.dispatchGlobalConversions(schemas);

    globalBinding.errorCheck();
  }
Beispiel #6
0
 /**
  * If the given component has {@link BIInlineBinaryData} customization, reflect that to the
  * specified property.
  */
 public static void handle(XSComponent source, CPropertyInfo prop) {
   BIInlineBinaryData inline =
       Ring.get(BGMBuilder.class).getBindInfo(source).get(BIInlineBinaryData.class);
   if (inline != null) {
     prop.inlineBinaryData = true;
     inline.markAsAcknowledged();
   }
 }
Beispiel #7
0
  /** Entry point. */
  public static Model build(
      XSSchemaSet _schemas, JCodeModel codeModel, ErrorReceiver _errorReceiver, Options opts) {
    // set up a ring
    final Ring old = Ring.begin();
    try {
      ErrorReceiverFilter ef = new ErrorReceiverFilter(_errorReceiver);

      Ring.add(XSSchemaSet.class, _schemas);
      Ring.add(codeModel);
      Model model =
          new Model(opts, codeModel, null /*set later*/, opts.classNameAllocator, _schemas);
      Ring.add(model);
      Ring.add(ErrorReceiver.class, ef);
      Ring.add(CodeModelClassFactory.class, new CodeModelClassFactory(ef));

      BGMBuilder builder =
          new BGMBuilder(
              opts.defaultPackage,
              opts.defaultPackage2,
              opts.isExtensionMode(),
              opts.getFieldRendererFactory());
      builder._build();

      if (ef.hadError()) return null;
      else return model;
    } finally {
      Ring.end(old);
    }
  }
Beispiel #8
0
 // can be null
 public JType getBaseType() {
   if (baseType != null && baseType.name != null) {
     return TypeUtil.getType(
         getCodeModel(), baseType.name, Ring.get(ErrorReceiver.class), getLocation());
   }
   BIProperty next = getDefault();
   if (next != null) return next.getBaseType();
   else return null;
 }
 JDefinedClass getClazz(ClassType t) {
   if (clazz != null) return clazz;
   try {
     JCodeModel codeModel = Ring.get(JCodeModel.class);
     clazz = codeModel._class(name, t);
     clazz.hide();
     return clazz;
   } catch (JClassAlreadyExistsException e) {
     return e.getExistingClass();
   }
 }
Beispiel #10
0
  /**
   * Finds a property customization that describes how the given component should be mapped to a
   * property (if it's mapped to a property at all.)
   *
   * <p>Consider an attribute use that does NOT carry a property customization. This schema
   * component is nonetheless considered to carry a (sort of) implicit property customization, whose
   * values are defaulted.
   *
   * <p>This method can be think of the method that returns this implied property customization.
   *
   * <p>Note that this doesn't mean the given component needs to be mapped to a property. But if it
   * does map to a property, it needs to follow this customization.
   *
   * <p>I think this semantics is next to non-sense but I couldn't think of any other way to follow
   * the spec.
   *
   * @param c A customization effective on this component will be returned. Can be null just to get
   *     the global customization.
   * @return Always return non-null valid object.
   */
  public static BIProperty getCustomization(XSComponent c) {
    BGMBuilder builder = Ring.get(BGMBuilder.class);

    // look for a customization on this component
    if (c != null) {
      BIProperty prop = builder.getBindInfo(c).get(BIProperty.class);
      if (prop != null) return prop;
    }

    // if no such thing exists, defeault.
    return getDefault(builder, c);
  }
Beispiel #11
0
  private void constantPropertyErrorCheck() {
    if (isConstantProperty != null && getOwner() != null) {
      // run additional check on the isCOnstantProperty value.
      // this value is not allowed if the schema component doesn't have
      // a fixed value constraint.
      //
      // the setParent method associates a customization with the rest of
      // XSOM object graph, so this is the earliest possible moment where
      // we can test this.

      if (!hasFixedValue.find(getOwner())) {
        Ring.get(ErrorReceiver.class).error(getLocation(), Messages.ERR_ILLEGAL_FIXEDATTR.format());
        // set this value to null to avoid the same error to be reported more than once.
        isConstantProperty = null;
      }
    }
  }
  /** Moves global BIConversion to the right object. */
  public void dispatchGlobalConversions(XSSchemaSet schema) {
    // also set parent to the global conversions
    for (Map.Entry<QName, BIConversion> e : globalConversions.entrySet()) {

      QName name = e.getKey();
      BIConversion conv = e.getValue();

      XSSimpleType st = schema.getSimpleType(name.getNamespaceURI(), name.getLocalPart());
      if (st == null) {
        Ring.get(ErrorReceiver.class)
            .error(getLocation(), Messages.ERR_UNDEFINED_SIMPLE_TYPE.format(name));
        continue; // abort
      }

      getBuilder().getOrCreateBindInfo(st).addDecl(conv);
    }
  }
Beispiel #13
0
/**
 * Root of the XML Schema binder.
 *
 * <p><div><img src="doc-files/binding_chart.png"/></div>
 *
 * @author Kohsuke Kawaguchi
 */
public class BGMBuilder extends BindingComponent {

  /** Entry point. */
  public static Model build(
      XSSchemaSet _schemas, JCodeModel codeModel, ErrorReceiver _errorReceiver, Options opts) {
    // set up a ring
    final Ring old = Ring.begin();
    try {
      ErrorReceiverFilter ef = new ErrorReceiverFilter(_errorReceiver);

      Ring.add(XSSchemaSet.class, _schemas);
      Ring.add(codeModel);
      Model model =
          new Model(opts, codeModel, null /*set later*/, opts.classNameAllocator, _schemas);
      Ring.add(model);
      Ring.add(ErrorReceiver.class, ef);
      Ring.add(CodeModelClassFactory.class, new CodeModelClassFactory(ef));

      BGMBuilder builder =
          new BGMBuilder(
              opts.defaultPackage,
              opts.defaultPackage2,
              opts.isExtensionMode(),
              opts.getFieldRendererFactory());
      builder._build();

      if (ef.hadError()) return null;
      else return model;
    } finally {
      Ring.end(old);
    }
  }

  /**
   * True if the compiler is running in the extension mode (as opposed to the strict conformance
   * mode.)
   */
  public final boolean inExtensionMode;

  /** If this is non-null, this package name takes over all the schema customizations. */
  public final String defaultPackage1;

  /** If this is non-null, this package name will be used when no customization is specified. */
  public final String defaultPackage2;

  private final BindGreen green = Ring.get(BindGreen.class);
  private final BindPurple purple = Ring.get(BindPurple.class);

  public final Model model = Ring.get(Model.class);

  public final FieldRendererFactory fieldRendererFactory;

  /**
   * Lazily computed {@link RefererFinder}.
   *
   * @see #getReferer
   */
  private RefererFinder refFinder;

  protected BGMBuilder(
      String defaultPackage1,
      String defaultPackage2,
      boolean _inExtensionMode,
      FieldRendererFactory fieldRendererFactory) {
    this.inExtensionMode = _inExtensionMode;
    this.defaultPackage1 = defaultPackage1;
    this.defaultPackage2 = defaultPackage2;
    this.fieldRendererFactory = fieldRendererFactory;

    DatatypeConverter.setDatatypeConverter(DatatypeConverterImpl.theInstance);

    promoteGlobalBindings();
  }

  private void _build() {
    // do the binding
    buildContents();
    getClassSelector().executeTasks();

    // additional error check
    // Reports unused customizations to the user as errors.
    Ring.get(UnusedCustomizationChecker.class).run();

    Ring.get(ModelChecker.class).check();
  }

  /** List up all the global bindings. */
  private void promoteGlobalBindings() {
    // promote any global bindings in the schema
    XSSchemaSet schemas = Ring.get(XSSchemaSet.class);

    for (XSSchema s : schemas.getSchemas()) {
      BindInfo bi = getBindInfo(s);

      // collect all global customizations
      model.getCustomizations().addAll(bi.toCustomizationList());

      BIGlobalBinding gb = bi.get(BIGlobalBinding.class);
      if (gb == null) continue;

      if (globalBinding == null) {
        globalBinding = gb;
        globalBinding.markAsAcknowledged();
      } else {
        // acknowledge this customization and report an error
        // otherwise the user will see "customization is attached to a wrong place" error,
        // which is incorrect
        gb.markAsAcknowledged();
        getErrorReporter().error(gb.getLocation(), Messages.ERR_MULTIPLE_GLOBAL_BINDINGS);
        getErrorReporter()
            .error(globalBinding.getLocation(), Messages.ERR_MULTIPLE_GLOBAL_BINDINGS_OTHER);
      }
    }

    if (globalBinding == null) {
      // no global customization is present.
      // use the default one
      globalBinding = new BIGlobalBinding();
      BindInfo big = new BindInfo();
      big.addDecl(globalBinding);
      big.setOwner(this, null);
    }

    // code generation mode
    model.strategy = globalBinding.getCodeGenerationStrategy();
    model.rootClass = globalBinding.getSuperClass();
    model.rootInterface = globalBinding.getSuperInterface();

    particleBinder =
        globalBinding.isSimpleMode() ? new ExpressionParticleBinder() : new DefaultParticleBinder();

    // check XJC extensions and realize them
    BISerializable serial = globalBinding.getSerializable();
    if (serial != null) {
      model.serializable = true;
      model.serialVersionUID = serial.uid;
    }

    // obtain the name conversion mode
    if (globalBinding.nameConverter != null) model.setNameConverter(globalBinding.nameConverter);

    // attach global conversions to the appropriate simple types
    globalBinding.dispatchGlobalConversions(schemas);

    globalBinding.errorCheck();
  }

  /**
   * Global bindings.
   *
   * <p>The empty global binding is set as the default, so that there will be no need to test if the
   * value is null.
   */
  private BIGlobalBinding globalBinding;

  /** Gets the global bindings. */
  public @NotNull BIGlobalBinding getGlobalBinding() {
    return globalBinding;
  }

  private ParticleBinder particleBinder;

  /** Gets the particle binder for this binding. */
  public @NotNull ParticleBinder getParticleBinder() {
    return particleBinder;
  }

  /**
   * Name converter that implements "XML->Java name conversion" as specified in the spec.
   *
   * <p>This object abstracts the detail that we use different name conversion depending on the
   * customization.
   *
   * <p>This object should be used to perform any name conversion needs, instead of the JJavaName
   * class in CodeModel.
   */
  public NameConverter getNameConverter() {
    return model.getNameConverter();
  }

  /** Fill-in the contents of each classes. */
  private void buildContents() {
    ClassSelector cs = getClassSelector();
    SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);

    for (XSSchema s : Ring.get(XSSchemaSet.class).getSchemas()) {
      BISchemaBinding sb = getBindInfo(s).get(BISchemaBinding.class);

      if (sb != null && !sb.map) {
        sb.markAsAcknowledged();
        continue; // no mapping for this package
      }

      getClassSelector()
          .pushClassScope(
              new CClassInfoParent.Package(getClassSelector().getPackage(s.getTargetNamespace())));

      checkMultipleSchemaBindings(s);
      processPackageJavadoc(s);
      populate(s.getAttGroupDecls(), s);
      populate(s.getAttributeDecls(), s);
      populate(s.getElementDecls(), s);
      populate(s.getModelGroupDecls(), s);

      // fill in typeUses
      for (XSType t : s.getTypes().values()) {
        stb.refererStack.push(t);
        model.typeUses().put(getName(t), cs.bindToType(t, s));
        stb.refererStack.pop();
      }

      getClassSelector().popClassScope();
    }
  }

  /** Reports an error if there are more than one jaxb:schemaBindings customization. */
  private void checkMultipleSchemaBindings(XSSchema schema) {
    ArrayList<Locator> locations = new ArrayList<Locator>();

    BindInfo bi = getBindInfo(schema);
    for (BIDeclaration bid : bi) {
      if (bid.getName() == BISchemaBinding.NAME) locations.add(bid.getLocation());
    }
    if (locations.size() <= 1) return; // OK

    // error
    getErrorReporter()
        .error(
            locations.get(0), Messages.ERR_MULTIPLE_SCHEMA_BINDINGS, schema.getTargetNamespace());
    for (int i = 1; i < locations.size(); i++)
      getErrorReporter()
          .error((Locator) locations.get(i), Messages.ERR_MULTIPLE_SCHEMA_BINDINGS_LOCATION);
  }

  /**
   * Calls {@link ClassSelector} for each item in the iterator to populate class items if there is
   * any.
   */
  private void populate(Map<String, ? extends XSComponent> col, XSSchema schema) {
    ClassSelector cs = getClassSelector();
    for (XSComponent sc : col.values()) cs.bindToType(sc, schema);
  }

  /** Generates <code>package.html</code> if the customization says so. */
  private void processPackageJavadoc(XSSchema s) {
    // look for the schema-wide customization
    BISchemaBinding cust = getBindInfo(s).get(BISchemaBinding.class);
    if (cust == null) return; // not present

    cust.markAsAcknowledged();
    if (cust.getJavadoc() == null) return; // no javadoc customization

    // produce a HTML file
    JTextFile html = new JTextFile("package.html");
    html.setContents(cust.getJavadoc());
    getClassSelector().getPackage(s.getTargetNamespace()).addResourceFile(html);
  }

  /**
   * Gets or creates the BindInfo object associated to a schema component.
   *
   * @return Always return a non-null valid BindInfo object. Even if no declaration was specified,
   *     this method creates a new BindInfo so that new decls can be added.
   */
  public BindInfo getOrCreateBindInfo(XSComponent schemaComponent) {

    BindInfo bi = _getBindInfoReadOnly(schemaComponent);
    if (bi != null) return bi;

    // XSOM is read-only, so we cannot add new annotations.
    // for components that didn't have annotations,
    // we maintain an external map.
    bi = new BindInfo();
    bi.setOwner(this, schemaComponent);
    externalBindInfos.put(schemaComponent, bi);
    return bi;
  }

  /** Used as a constant instance to represent the empty {@link BindInfo}. */
  private final BindInfo emptyBindInfo = new BindInfo();

  /**
   * Gets the BindInfo object associated to a schema component.
   *
   * @return always return a valid {@link BindInfo} object. If none is specified for the given
   *     component, a dummy empty BindInfo will be returned.
   */
  public BindInfo getBindInfo(XSComponent schemaComponent) {
    BindInfo bi = _getBindInfoReadOnly(schemaComponent);
    if (bi != null) return bi;
    else return emptyBindInfo;
  }

  /**
   * Gets the BindInfo object associated to a schema component.
   *
   * @return null if no bind info is associated to this schema component.
   */
  private BindInfo _getBindInfoReadOnly(XSComponent schemaComponent) {

    BindInfo bi = externalBindInfos.get(schemaComponent);
    if (bi != null) return bi;

    XSAnnotation annon = schemaComponent.getAnnotation();
    if (annon != null) {
      bi = (BindInfo) annon.getAnnotation();
      if (bi != null) {
        if (bi.getOwner() == null) bi.setOwner(this, schemaComponent);
        return bi;
      }
    }

    return null;
  }

  /** A map that stores binding declarations augmented by XJC. */
  private final Map<XSComponent, BindInfo> externalBindInfos = new HashMap<XSComponent, BindInfo>();

  /** Gets the {@link BIDom} object that applies to the given particle. */
  protected final BIDom getLocalDomCustomization(XSParticle p) {
    if (p == null) {
      return null;
    }
    BIDom dom = getBindInfo(p).get(BIDom.class);
    if (dom != null) return dom;

    // if not, the term might have one.
    dom = getBindInfo(p.getTerm()).get(BIDom.class);
    if (dom != null) return dom;

    XSTerm t = p.getTerm();
    // type could also have one, in case of the dom customization
    if (t.isElementDecl()) return getBindInfo(t.asElementDecl().getType()).get(BIDom.class);
    // similarly the model group in a model group definition may have one.
    if (t.isModelGroupDecl())
      return getBindInfo(t.asModelGroupDecl().getModelGroup()).get(BIDom.class);

    return null;
  }

  /** Returns true if the component should be processed by purple. */
  private final XSFinder toPurple =
      new XSFinder() {
        public Boolean attributeUse(XSAttributeUse use) {
          // attribute use always maps to a property
          return true;
        }

        public Boolean simpleType(XSSimpleType xsSimpleType) {
          // simple type always maps to a type, hence we should take purple
          return true;
        }

        public Boolean wildcard(XSWildcard xsWildcard) {
          // attribute wildcards always maps to a property.
          // element wildcards should have been processed with particle binders
          return true;
        }
      };
  /**
   * If the component maps to a property, forwards to purple, otherwise to green.
   *
   * <p>If the component is mapped to a type, this method needs to return true. See the chart at the
   * class javadoc.
   */
  public void ying(XSComponent sc, @Nullable XSComponent referer) {
    if (sc.apply(toPurple) == true || getClassSelector().bindToType(sc, referer) != null)
      sc.visit(purple);
    else sc.visit(green);
  }

  private Transformer identityTransformer;

  /** Gets the shared instance of the identity transformer. */
  public Transformer getIdentityTransformer() {
    try {
      if (identityTransformer == null)
        identityTransformer = TransformerFactory.newInstance().newTransformer();
      return identityTransformer;
    } catch (TransformerConfigurationException e) {
      throw new Error(e); // impossible
    }
  }

  /** Find all types that refer to the given complex type. */
  public Set<XSComponent> getReferer(XSType c) {
    if (refFinder == null) {
      refFinder = new RefererFinder();
      refFinder.schemaSet(Ring.get(XSSchemaSet.class));
    }
    return refFinder.getReferer(c);
  }

  /**
   * Returns the QName of the declaration.
   *
   * @return null if the declaration is anonymous.
   */
  public static QName getName(XSDeclaration decl) {
    String local = decl.getName();
    if (local == null) return null;
    return new QName(decl.getTargetNamespace(), local);
  }

  /**
   * Derives a name from a schema component.
   *
   * <p>This method handles prefix/suffix modification and XML-to-Java name conversion.
   *
   * @param name The base name. This should be things like element names or type names.
   * @param comp The component from which the base name was taken. Used to determine how names are
   *     modified.
   */
  public String deriveName(String name, XSComponent comp) {
    XSSchema owner = comp.getOwnerSchema();

    name = getNameConverter().toClassName(name);

    if (owner != null) {
      BISchemaBinding sb = getBindInfo(owner).get(BISchemaBinding.class);

      if (sb != null) name = sb.mangleClassName(name, comp);
    }

    return name;
  }

  public boolean isGenerateMixedExtensions() {
    if (globalBinding != null) {
      return globalBinding.isGenerateMixedExtensions();
    }
    return false;
  }
}
 public void onSetOwner() {
   super.onSetOwner();
   // if one is given by options, use that
   NameConverter nc = Ring.get(Model.class).options.getNameConverter();
   if (nc != null) nameConverter = nc;
 }