What is the role of ClassOutline / JClass / CClass in CodeModel?

My question is about writing JAXB plugins, in particular JAXB code.

What is the role of ClassOutline (and companions ) and JClass (and companions ) and CClass (and companions )? When viewing the list of classes in the respective packages, it is not clear what the chicken is and what the egg is.

My interpretation is that CClass ( CPropertyInfo , CEnumConstant , ...) are created by XJC when they first analyze XSD projects. Then some kind of magic happens, and this model is converted to JClass ( JFieldVar , JEnumConstant , ...), and settings are applied during this conversion. After that, plugins are launched. ClassOutline used as a bridge between the two models. In general, it looks very difficult.

In these parallel models, I believe that the same information can be obtained in several ways. For example, the class field type:

  • JClass#fields()JFieldVar#typeJType
  • CClassInfo#getProperties()CPropertyInfo#baseTypeJType

I am looking for a detailed explanation of the life cycle of the above models. Thanks.

+7
source share
2 answers

Oh, oh, someone is interested in the internal environment of XJC. I could help, since I probably developed more JAXB plugins than anyone else (see JAXB2 Basics )

Ok, let it begin. In XJC, the schema compiler does something like this

  • Parses the circuit
  • Creates a schema model (CClass, CPropertyInfo, etc.)
  • Creates a path (ClassOutline, FieldOutline, etc.).
  • Displays the code model (JClass, JDefinedClass, JMethod, etc.).
  • Writes physical code (e.g. Java files to disk)

Let's start with the last two.

Java files do not need explanation, I hope.

A code model is also a very simple task. This is an API that you can use to programmatically develop Java code. Instead, you can just use string concatenation, but it is much more error prone. With CodeModel, you are almost guaranteed to get at least grammatically correct Java code. Therefore, I hope this part is also clear. (By the way, I really like CodeModel. I recently wrote JavaScript code based on the ideas of CodeModel.)

Now let's look at the "model" and the "outline". The model is the result of parsing the incoming circuit. It models the designs of the input circuit, mainly in terms of “classes” that correspond to complex types and “properties” that correspond to elements, attributes and values ​​(for example, when you have a complex type with simple content).

A model should be understood as a logical modeling construct close to XML and schema. Thus, it simply describes the types and properties that they have. Of course, it’s much more complicated that I describe it, there are all kinds of exceptions and caveats - starting with wilcard (xsd: any) types, permutation groups, enumerations, built-in types, etc.

Interestingly enough, the sibling Model is a RuntimeTypeInfoSetImpl that is used by JAXB at runtime. Thus, it is also a type of model that, however, is not parsed from an XML schema, but rather from JAXB annotations in classes. The concept is the same. Both models and RuntimeTypeInfoSetImpl implement the TypeInfoSet interface, which is a superconstruction. Check interfaces such as ClassInfo and PropertyInfo - they have an implementation for both compile time ( CClassInfo and CPropertyInfo in XJC) and runtime ( RuntimeClassInfoImpl , etc. For JAXB RI).

So, when the XJC parsed and parsed the schema, you have a Model . This Model cannot yet create code. There are different strategies for creating code. You can only generate annotated classes, or you can create an interface / implementation of a pair of classes, as in JAXB 1. All code generation is not really the task of the model. Moreover, there are a number of aspects that are relevant to the physical nature of Java code, but not very relevant to the model. For example, you need to group classes into packages. This is due to the Java packaging system, not the properties of the model itself.

And here the contours come into play. You can see the contours as a step between the circuit model and the code model. You can view contours as factories for code model elements responsible for organizing code and generating JDefinedClass es from CClassInfo s.

So you are right, it is really very difficult. I am not a Sun / Oracle employee, I did not design it (I know the person who did this, although I respected him very much). I can guess a few reasons for some design decisions, for example:

  • Use the same interfaces for compile time and runtime models.
  • Allow various code generation strategies
  • Allow plugins to manage the created model

I agree that this design is very complex, but it has its own reasons. One of the proofs of this is that it was actually possible to build a mapping generator for XML-to-JavaScript mappings - basically on the same models. I just had to replace the code generation, leaving the circuit analysis intact. (See Jsonix for this.)

Well, I hope I shed some light on why things in XJC are like them. Good luck with these APIs, they are not scary. Feel free to check your existing open source code, there are many examples available.

ps. Actually always wanted to write this. :)

+17
source

(This is the answer to your further questions.)

Yes, you can check the settings. Here is the class that I use to access the settings.

The trick is that the link properties do not have their own settings; the settings are placed in the link element properties.

 public static CCustomizations getCustomizations( final CPropertyInfo propertyInfo) { final CCustomizations main = new CCustomizations( propertyInfo.getCustomizations()); final Collection<CCustomizations> elementCustomizations = propertyInfo .accept(new CPropertyVisitor<Collection<CCustomizations>>() { public Collection<CCustomizations> onAttribute( CAttributePropertyInfo info) { return Collections.emptyList(); } public Collection<CCustomizations> onElement( CElementPropertyInfo arg0) { return Collections.emptyList(); } public Collection<CCustomizations> onReference( CReferencePropertyInfo info) { final List<CCustomizations> elementCustomizations = new ArrayList<CCustomizations>( info.getElements().size()); for (CElement element : info.getElements()) { if (!(element instanceof CElementInfo && ((CElementInfo) element) .hasClass())) { elementCustomizations.add(element .getCustomizations()); } } return elementCustomizations; } public Collection<CCustomizations> onValue( CValuePropertyInfo arg0) { return Collections.emptyList(); }; }); CCustomizations customizations = main; for (CCustomizations e : elementCustomizations) { main.addAll(e); } return customizations; } 

I would say that users@jaxb.java.net is a good place for such discussions.

+2
source

All Articles