DOM code generator: Difference between revisions

From COLLADA Public Wiki
Jump to navigation Jump to search
(editing first pass, mostly formatting, plus some questions)
(Removed vandalism)
 
(29 intermediate revisions by 4 users not shown)
Line 1: Line 1:
'''Summary:'''  The '''COLLADA Code Generator''' is/does ''((ANDY: fill in summary))''.
'''Summary:'''  The '''COLLADA DOM code generator''' is an external application that is used to generate the C++ classes that are used in the [[COLLADA DOM]].
 
==Obtaining the code generator==
The code generator comes with the DOM itself, in the codeGen folder. A readme is provided that explains how to run the code generator.


==DOM generated types==
==DOM generated types==
DOM type information is stored in:


The DOM's basic types are defined in '''daeTypes.h'''. There are mappings from XML Schema basic types to DOM types in '''daeDomTypes.h'''.
* <code>daeTypes.h</code>, the DOM's basic types  
 
* <code>daeDomTypes.h</code>, mappings from XML Schema basic types to DOM types
Any other new types defined in the schema document generate new atomic types or add name bindings to existing atomic types in the DOM.
* <code>domTypes.h</code> types generated by the code generator
 
All types defined in the schema are either restrictions, extensions, unions, or lists of existing types.


The DOM generates types in '''domTypes.h'''.
Any other new types defined in the COLLADA schema document generate new atomic types or add name bindings to existing atomic types in the DOM. All types defined in the COLLADA schema are restrictions, extensions, unions, or lists of existing types.


The format for most type declarations is:
===Type declaration formats===
{|
|-
!For what||Format
|-
|most type declarations||
  typedef ''base_type_name'' ''domNew_type_name''  
  typedef ''base_type_name'' ''domNew_type_name''  
 
|-
The format for list types is:
|list types||
  typedef daeTArray< ''base_type_name'' > ''domNew_type_name''
  typedef daeTArray< ''base_type_name'' > ''domNew_type_name''
|-
|enum types||
enum dom''New_type_name''
Each enum value is then created as <code>''NEW_TYPE_NAME''_Enum</code>
|-
|union types||Supported only for unions of enums. A new enum is generated for that union type containing the symbols and values of all enums contained in the union.
|}


Enum types take the form of “enum dom''New_type_name''”. Each enum value is then created as “''NEW_TYPE_NAME''_Enum”.
===Code for registered types===
 
All generated types are registered in the <code>registerDomTypes</code> function found in <code>domTypes.cpp</code>. For all types except enums, code is generated that looks like  
Union types are supported only for unions of enums. A new enum is generated for that union type containing the symbols and values of all enums contained in the union.
 
These types are registered in the '''registerDomTypes''' function found in '''domTypes.cpp'''. For all types except enums code is generated that looks like  
  type = daeAtomicType::get("base_type_name");
  type = daeAtomicType::get("base_type_name");
if ( type == NULL ) { //register as a raw type
    if ( type == NULL ) { //register as a raw type
type = new daeRawRefType;
      type = new daeRawRefType;
type->_nameBindings.append("new_type_name");
        type->_nameBindings.append("new_type_name");
daeAtomicType::append( type );
            daeAtomicType::append( type );
}
        }
else { //add binding to existing type
    else { //add binding to existing type
type->_nameBindings.append("new_type_name ");
        type->_nameBindings.append("new_type_name ");
}
        }
This code searches for a type for the '''base_type_name'''. If it finds one, it adds '''new_type_name''' as a name binding for that type. If the base type does not exist then a new '''rawRefType''' is created.
This code searches for a type for the <code>base_type_name</code>. If it finds one, it adds <code>new_type_name</code> as a name binding for that type. If the base type does not exist then a new <code>rawRefType</code> is created.
 
Enums always get a new type generated. The two arrays '''_strings''' and '''_values''' are populated with the enum values.


In the schema, if an enumeration has an '''<xs:annotation>''' with an '''<xs:appinfo> value=''value''''', the enum created will have a '''value''' value.
===Enumerated types===
A new type is always generated for enums. The arrays <code>_strings</code> and <code>_values</code> are populated with the enum values. In the schema, if an enumeration has an <xs:annotation> with an <xs:appinfo> value=''value'', the enum created will have a ''value'' value.


==DOM-generated classes==
==DOM-generated classes==
===Interface===
===Interface===


Each '''<xs:element> <xs:group>''' and '''<xs:complexType>''' generates a new '''daeElement''' subclass name '''dom''Element_name'''''.
Each <xs:element>, <xs:group>, and <xs:complexType> generates a new <code>daeElement</code> subclass name <code>dom''Element_name''</code>.


Each attribute and child element and a value (if it has one) gets its data storage and accessor and mutators. Array types and URIs are returned by reference. All other types are returned by value.
Each attribute and child element and a value (if it has one) gets its data storage and accessor and mutators. Array types and URIs are returned by reference. All other types are returned by value.


If an element has an '''xs:choice''' content model group and more than a single child element, it will have  '''_contents''', '''_contentsOrder''', and '''_CMData''' arrays to store the data needed to represent the ordering of children in the content model.
If an element has an <xs:choice> content model group and more than a single child element, it will have  <code>_contents</code>, <code>_contentsOrder</code>, and <code>_CMData</code> arrays to store the data needed to represent the ordering of children in the content model.


An '''xs:complexType''' generates two classes:
An <xs:complexType> generates two classes:
* The class description/interface.
* The class description/interface.
* A '''daeElement''' subclass that inherits from both '''daeElement''' and the new class interface.
* A <code>daeElement</code> subclass that inherits from both <code>daeElement</code> and the new class interface.


Any class defined in XMLSchema global scope (not defined as a child of another element) generates a new '''daeElement''' subclass. This new element, if the type attribute is a complex type, also inherits from the complex type interface and '''daeElement'''.
Any class defined in XMLSchema global scope (not defined as a child of another element) generates a new <code>daeElement</code> subclass. This new element, if the type attribute is a complex type, also inherits from the complex type interface and <code>daeElement</code>.


An element that is part of a substitution group inherits from the element it is substitutable for. Then the DOM uses polymorphism and stores a pointer to the base class, which could be an object of any of the substitutable classes.
An element that is part of a substitution group inherits from the element it is substitutable for. Then the DOM uses polymorphism and stores a pointer to the base class, which could be an object of any of the substitutable classes.


The code generator allows for schema type inheritance by either extension or restriction. In either case the new class inherits from the base class. Restriction is handled with the DOM meta information since C++ can do inheritance only by extension. The current (COLLADA 1.4.1) schema does not take advantage of this feature.
The code generator allows for schema type inheritance by either extension or restriction. In either case, the new class inherits from the base class. Restriction is handled with the DOM meta information because C++ can do inheritance only by extension. The current (COLLADA 1.4.1) schema does not take advantage of this feature.


The code generator allows for scoped type definitions. This would happen when a simple type is created anonymously in the schema document instead of creating a global simple type and referencing it. The current (COLLADA 1.4.1) schema does not take advantage of this feature.
The code generator allows for scoped type definitions. This happens when a simple type is created anonymously in the schema document instead of creating a global simple type and referencing it. The current (COLLADA 1.4.1) schema does not take advantage of this feature.


When generating mutators for string data attributes or values, the generator creates code:
When generating mutators for string data attributes or values, the generator creates code:
Line 62: Line 72:
which lets the DOM create memory to store its string data.
which lets the DOM create memory to store its string data.


The '''xmlns''' attribute is specially created only for elements that have an '''<xs:annotation> <xs:appinfo>''' that contains '''enable-xmlns'''.
The ''xmlns'' attribute is created only for elements that have an <xs:annotation> <xs:appinfo> that contains '''enable-xmlns'''.


===Meta generation===
===Meta generation===


Each element that is generated has a function ''registerElement''. This is the function that is called to create the meta information that describes the new element.
Each element that is generated has a function <code>registerElement</code>. This is the function that is called to create the meta information that describes the new element.


Every element’s '''_Meta''' descriptor has a name and a pointer to the element’s creation function '''create(daeInt bytes)'''.
Every element’s <code>_Meta</code> descriptor has a name and a pointer to the element’s creation function <code>create(daeInt bytes)</code>.


If the new element is created from an '''<xs:group>''' then the meta is tagged as ''transparent''. Transparent means that the IOplugin will not create an XML tag or any attributes for this element when it is saved. Essentially, the transparent flag means that the element exists in the COLLADA DOM content but doesn’t really exist in the XML content.
If the new element is created from an <xs:group> then the meta is tagged as ''transparent''. Transparent means that the <code>IOplugin</code> will not create an XML tag or any attributes for this element when it is saved. Essentially, the transparent flag means that the element exists in the COLLADA DOM content but doesn’t really exist in the XML content.


If the new element is abstract, the '''abstract''' flag is set for the meta. Abstract elements cannot be placed in the DOM.
If the new element is abstract, the <code>abstract</code> flag is set for the meta. Abstract elements cannot be placed in the DOM.


If the element is not declared in the schema’s global scope then the '''isInnerClass''' flag is set to true. This flag is used by the '''metaAny''' content model group. Any globally declared elements can be created as part of the “any” content model but not ''((ANDY: as part of?))'' scoped inner classes. Any other children of an “any” group become the weakly typed '''domAny''' elements.
If the element is not declared in the schema’s global scope then the <code>isInnerClass</code> flag is set to true. This flag is used by the <code>metaAny</code> content model group. Any globally declared elements can be created as part of the “any” content model, but elements declared as inner classes can not. Any other children of an “any” group become the weakly typed <code>domAny</code> elements.


Each attribute has a new '''metaAttribute''' or '''metaArrayAttribute''' created to describe it. This '''metaAttribute''' is given a name, a type, and the pointer offset into the class where the data can be found.
Each attribute has a new <code>metaAttribute</code> or <code>metaArrayAttribute</code> created to describe it. This <code>metaAttribute</code> is given a name, a type, and the pointer offset into the class where the data can be found. If the attribute is marked ''required'' or given a default value, that is also set on the <code>metaAttribute</code>.


The value is treated the same as a normal attribute.
When a COLLADA element can have character content, the content is usually stored in a variable called <code>_value</code> in the corresponding DOM class. This value is treated the same as a normal attribute.


If the attribute is marked required or given a default value, that is also set on the '''metaAttribute'''.
The <code>metaCMPolicy</code> object tree is generated to match the content model specified in the schema. Only the '''xs:any''' content model group is not supported.


The '''metaCMPolicy''' object tree is generated to match the content model specified in the schema. Only the '''xs:any''' content model group is not supported.
Any content model that contains either an element that is the base for a substitution group or both a choice and more than one child element  will have <code>contents</code> and <code>contentsOrder</code> <code>metaAttribute</code>s added.  


Any content model that contains a choice and more than one child element or an element that is the base for a substitution group will have '''_contents''' and '''_contentsOrder''' '''metaAttribute'''s added. ''((ANDY: Not sure where parens go around ands/ors at beginning of this sentence.))''
If the element’s content model contains an '''xs:choice''' group then the meta will have a <code>CMData</code> <code>metaAttribute</code> created.
 
If the element’s content model contains an '''xs:choice''' group then the meta will have a '''_CMData''' '''metaAttribute''' created.


==Code generator program flow and systems==
==Code generator program flow and systems==


The code generator is run by starting '''gen.php''' with a php interpreter. The '''gen.php''' requires at least one argument, which is the schema to use for code generation.
The code generator is run by starting <code>gen.php</code> with a php interpreter. Arguments include:
 
{| style="border:1px solid #999999;border-collapse: collapse;" border=1
The generator, by default, creates the full integration classes. Pass an argument (after the schema) '''min''' to generate the minimal integration classes.
|-
 
|''schema_name''||The schema to use for code generation. Required.
The generator, by default, puts the SCEA SNIP copyright as the header of all of the files. Pass an argument '''cprt''' for the generator to use the SCEA Shared Source License copyright as the header. This is the way the generated classes should be created.
|-
 
|<code>min</code>  (after the schema) || Generate the minimal integration classes. By default, the generator creates the full integration classes.  
The generator starts by parsing the schema document and creating its own DOM-like structure to store the info from the schema.
|-
 
|<code>cprt</code>|| Use the SCEA Shared Source License copyright as the header. This is the way the generated classes should be created. By default, the generator puts the SCEA SNIP copyright as the header of all of the files.  
For each schema element that might be encountered, there needs to be a source file '''xs''ElementName''.php'''. This class is used to store the data related to that element. The source file needs to be included ('''require_once''' in PHP) in the '''object-model.php''' file.
|}


Each of the object model classes has a constructor that registers what elements and attributes (along with their '''min''' and '''maxOccurs''') are valid for that element.
So, for example, you might run
gen.php colladaSchema14.xsd cprt


The '''SchemaParser''' class uses the default PHP SAX XML parser to parse the schema document and create the custom DOM used for code generation.
The generator does the following:
# Parses the schema document and creates its own DOM-like structure to store the info from the schema.
# For each schema element that might be encountered, there needs to be a source file <code>xs''ElementName''.php</code>. This class is used to store the data related to that element. The source file needs to be included ('''require_once''' in PHP) in the <code>object-model.php</code> file. {{editor|what=the preceding isn't really a step...need to convert}}
# Each of the object model classes has a constructor that registers what elements and attributes (along with their '''min''' and '''maxOccurs''') are valid for that element. {{editor|what=ditto}}
# The <code>SchemaParser</code> class uses the default PHP SAX XML parser to parse the schema document and create the custom DOM used for code generation.
# Gets all elements that are '''xs:simpleType''' and calls <code>generate</code> on them, which in turn creates a <code>TypeMeta</code> object that contains the data needed to generate the COLLADA simple types.
# Does the same for <xs:complexType>,  <xs:group>, and <xs:element>.


The generator then gets all elements that are '''xs:simpleType''' and calls generate on them. Generate creates a '''TypeMeta''' object that contains the data needed to generate the COLLADA simple types.
The <code>template-engine</code> source file contains the logic on how to apply a template. Templates suffixed with <code>–file</code>, contain the logic for creating a new C++ source or header file and applying another template to actually write the C++ code.


Then the generator does the same for '''xs:complexType,  xs:group, and xs:element'''.
The most significant templates are:
* <code>tpl-types-header.php</code> for generated type definitions
* <code>tpl-types-cpp.php</code> for type registration
* <code>tpl-class-def.php</code> for generated class interfaces
* <code>tpl-cpp-methods</code> for the generation of the meta for each class.


The '''template-engine''' source file contains the logic on how to apply a template. Templates take the form of two source files:
{{DOM navigation}}
* One, usually suffixed with '''–file''', contains the logic on creating a new c++ source or header file and then applying another template to actually write the code.
*''((ANDY: Is this the second of the 2 source files? Wasn't entirely clear) The most significant templates are  one of:
** '''tpl-types-header.php''' for generated type definitions
**'''tpl-types-cpp.php''' for type registration
**'''tpl-class-def.php''' for generated class interfaces
**'''tpl-cpp-methods''' for the generation of the meta for each class.


[[Category:DOM project|code generator]]
[[Category:COLLADA DOM|Code generator]]

Latest revision as of 13:17, 12 November 2012

Summary: The COLLADA DOM code generator is an external application that is used to generate the C++ classes that are used in the COLLADA DOM.

Obtaining the code generator

The code generator comes with the DOM itself, in the codeGen folder. A readme is provided that explains how to run the code generator.

DOM generated types

DOM type information is stored in:

  • daeTypes.h, the DOM's basic types
  • daeDomTypes.h, mappings from XML Schema basic types to DOM types
  • domTypes.h types generated by the code generator

Any other new types defined in the COLLADA schema document generate new atomic types or add name bindings to existing atomic types in the DOM. All types defined in the COLLADA schema are restrictions, extensions, unions, or lists of existing types.

Type declaration formats

For what Format
most type declarations
typedef base_type_name domNew_type_name 
list types
typedef daeTArray< base_type_name > domNew_type_name
enum types
enum domNew_type_name

Each enum value is then created as NEW_TYPE_NAME_Enum

union types Supported only for unions of enums. A new enum is generated for that union type containing the symbols and values of all enums contained in the union.

Code for registered types

All generated types are registered in the registerDomTypes function found in domTypes.cpp. For all types except enums, code is generated that looks like

type = daeAtomicType::get("base_type_name");
   if ( type == NULL ) { //register as a raw type
      type = new daeRawRefType;
       type->_nameBindings.append("new_type_name");
           daeAtomicType::append( type );  
       }
   else { //add binding to existing type
       type->_nameBindings.append("new_type_name ");
       }

This code searches for a type for the base_type_name. If it finds one, it adds new_type_name as a name binding for that type. If the base type does not exist then a new rawRefType is created.

Enumerated types

A new type is always generated for enums. The arrays _strings and _values are populated with the enum values. In the schema, if an enumeration has an <xs:annotation> with an <xs:appinfo> value=value, the enum created will have a value value.

DOM-generated classes

Interface

Each <xs:element>, <xs:group>, and <xs:complexType> generates a new daeElement subclass name domElement_name.

Each attribute and child element and a value (if it has one) gets its data storage and accessor and mutators. Array types and URIs are returned by reference. All other types are returned by value.

If an element has an <xs:choice> content model group and more than a single child element, it will have _contents, _contentsOrder, and _CMData arrays to store the data needed to represent the ordering of children in the content model.

An <xs:complexType> generates two classes:

  • The class description/interface.
  • A daeElement subclass that inherits from both daeElement and the new class interface.

Any class defined in XMLSchema global scope (not defined as a child of another element) generates a new daeElement subclass. This new element, if the type attribute is a complex type, also inherits from the complex type interface and daeElement.

An element that is part of a substitution group inherits from the element it is substitutable for. Then the DOM uses polymorphism and stores a pointer to the base class, which could be an object of any of the substitutable classes.

The code generator allows for schema type inheritance by either extension or restriction. In either case, the new class inherits from the base class. Restriction is handled with the DOM meta information because C++ can do inheritance only by extension. The current (COLLADA 1.4.1) schema does not take advantage of this feature.

The code generator allows for scoped type definitions. This happens when a simple type is created anonymously in the schema document instead of creating a global simple type and referencing it. The current (COLLADA 1.4.1) schema does not take advantage of this feature.

When generating mutators for string data attributes or values, the generator creates code:

*(daeStringRef*)&attrAttribute_name = atAttribute_name 

which lets the DOM create memory to store its string data.

The xmlns attribute is created only for elements that have an <xs:annotation> <xs:appinfo> that contains enable-xmlns.

Meta generation

Each element that is generated has a function registerElement. This is the function that is called to create the meta information that describes the new element.

Every element’s _Meta descriptor has a name and a pointer to the element’s creation function create(daeInt bytes).

If the new element is created from an <xs:group> then the meta is tagged as transparent. Transparent means that the IOplugin will not create an XML tag or any attributes for this element when it is saved. Essentially, the transparent flag means that the element exists in the COLLADA DOM content but doesn’t really exist in the XML content.

If the new element is abstract, the abstract flag is set for the meta. Abstract elements cannot be placed in the DOM.

If the element is not declared in the schema’s global scope then the isInnerClass flag is set to true. This flag is used by the metaAny content model group. Any globally declared elements can be created as part of the “any” content model, but elements declared as inner classes can not. Any other children of an “any” group become the weakly typed domAny elements.

Each attribute has a new metaAttribute or metaArrayAttribute created to describe it. This metaAttribute is given a name, a type, and the pointer offset into the class where the data can be found. If the attribute is marked required or given a default value, that is also set on the metaAttribute.

When a COLLADA element can have character content, the content is usually stored in a variable called _value in the corresponding DOM class. This value is treated the same as a normal attribute.

The metaCMPolicy object tree is generated to match the content model specified in the schema. Only the xs:any content model group is not supported.

Any content model that contains either an element that is the base for a substitution group or both a choice and more than one child element will have contents and contentsOrder metaAttributes added.

If the element’s content model contains an xs:choice group then the meta will have a CMData metaAttribute created.

Code generator program flow and systems

The code generator is run by starting gen.php with a php interpreter. Arguments include:

schema_name The schema to use for code generation. Required.
min (after the schema) Generate the minimal integration classes. By default, the generator creates the full integration classes.
cprt Use the SCEA Shared Source License copyright as the header. This is the way the generated classes should be created. By default, the generator puts the SCEA SNIP copyright as the header of all of the files.

So, for example, you might run

gen.php colladaSchema14.xsd cprt

The generator does the following:

  1. Parses the schema document and creates its own DOM-like structure to store the info from the schema.
  2. For each schema element that might be encountered, there needs to be a source file xsElementName.php. This class is used to store the data related to that element. The source file needs to be included (require_once in PHP) in the object-model.php file.

((EDITOR: This page needs the following improvement: the preceding isn't really a step...need to convert ))

  1. Each of the object model classes has a constructor that registers what elements and attributes (along with their min and maxOccurs) are valid for that element.

((EDITOR: This page needs the following improvement: ditto ))

  1. The SchemaParser class uses the default PHP SAX XML parser to parse the schema document and create the custom DOM used for code generation.
  2. Gets all elements that are xs:simpleType and calls generate on them, which in turn creates a TypeMeta object that contains the data needed to generate the COLLADA simple types.
  3. Does the same for <xs:complexType>, <xs:group>, and <xs:element>.

The template-engine source file contains the logic on how to apply a template. Templates suffixed with –file, contain the logic for creating a new C++ source or header file and applying another template to actually write the C++ code.

The most significant templates are:

  • tpl-types-header.php for generated type definitions
  • tpl-types-cpp.php for type registration
  • tpl-class-def.php for generated class interfaces
  • tpl-cpp-methods for the generation of the meta for each class.


COLLADA DOM - Version 2.4 Historical Reference
List of main articles under the DOM portal.
User Guide chapters:  • Intro  • Architecture  • Setting up  • Working with documents  • Creating docs  • Importing docs  • Representing elements  • Working with elements  • Resolving URIs  • Resolving SIDs  • Using custom COLLADA data  • Integration templates  • Error handling

Systems:  • URI resolver  • Meta  • Load/save flow  • Runtime database  • Memory • StringRef  • Code generator
Additional information:  • What's new  • Backward compatibility  • Future work
Terminology categories:  • COLLADA  • DOM  • XML