/*==================================================================*\
| EXIP - Embeddable EXI Processor in C |
|--------------------------------------------------------------------|
| This work is licensed under BSD 3-Clause License |
| The full license terms and conditions are located in LICENSE.txt |
\===================================================================*/
/**
* @file treeTableSchema.h
* @brief Defining a TreeTable structure for schema definitions;
* Functions for converting the XML schema definitions to a TreeTable structure, and TreeTable manipulations
* @date Mar 13, 2012
* @author Rumen Kyusakov
* @author Robert Cragie
* @version 0.5
* @par[Revision] $Id: treeTableSchema.h 332 2014-05-05 18:22:55Z kjussakov $
*/
#ifndef TREETABLESCHEMA_H_
#define TREETABLESCHEMA_H_
/**
* The process for generating an EXIPSchema object is the following:
* First the XML schema file(s) is/are converted to a TreeTable structure(s) - treeTableBuild.c
* Then the TreeTable structures are rationalize and linked - links base types to derived types, elements to types etc. - treeTableManipulate.c
* Finally the TreeTable structures are converted to EXIPSchema object - treeTableToGrammars.c
*/
#include "procTypes.h"
#include "dynamicArray.h"
#include "protoGrammars.h"
#include "hashtable.h"
#include "grammarGenerator.h"
/**
* @page XMLSchemaID SchemaID of XML Schema files
*
* The value of the SchemaID field of the EXI header
* that should be used when processing EXI encoded XML schemas
* in schema mode by exip is the XML Schema target namespace:
* @code
* http://www.w3.org/2001/XMLSchema
* @endcode
*/
/** Enumeration of elements found in the schema */
enum ElemEnum
{
ELEMENT_ELEMENT =0,
ELEMENT_ATTRIBUTE =1,
ELEMENT_CHOICE =2,
ELEMENT_COMPLEX_TYPE =3,
ELEMENT_COMPLEX_CONTENT =4,
ELEMENT_GROUP =5,
ELEMENT_IMPORT =6,
ELEMENT_SEQUENCE =7,
ELEMENT_ALL =8,
ELEMENT_EXTENSION =9,
ELEMENT_RESTRICTION =10,
ELEMENT_SIMPLE_CONTENT =11,
ELEMENT_ANY =12,
ELEMENT_SIMPLE_TYPE =13,
ELEMENT_MIN_INCLUSIVE =14,
ELEMENT_ANNOTATION =15,
ELEMENT_DOCUMENTATION =16,
ELEMENT_MAX_LENGTH =17,
ELEMENT_MAX_INCLUSIVE =18,
ELEMENT_LIST =19,
ELEMENT_UNION =20,
ELEMENT_ATTRIBUTE_GROUP =21,
ELEMENT_ANY_ATTRIBUTE =22,
ELEMENT_ENUMERATION =23,
ELEMENT_KEY =24,
ELEMENT_SELECTOR =25,
ELEMENT_FIELD =26,
ELEMENT_NOTATION =27,
ELEMENT_INCLUDE =28,
ELEMENT_REDEFINE =29,
ELEMENT_MIN_EXCLUSIVE =30,
ELEMENT_MAX_EXCLUSIVE =31,
ELEMENT_TOTAL_DIGITS =32,
ELEMENT_FRACTION_DIGITS =33,
ELEMENT_LENGTH =34,
ELEMENT_MIN_LENGTH =35,
ELEMENT_WHITE_SPACE =36,
ELEMENT_PATTERN =37,
ELEMENT_APPINFO =38,
ELEMENT_VOID =39
};
typedef enum ElemEnum ElemEnum;
/** Codes for the attributes found in the schema */
enum AttrEnum
{
ATTRIBUTE_NAME =0,
ATTRIBUTE_TYPE =1,
ATTRIBUTE_REF =2,
ATTRIBUTE_MIN_OCCURS =3,
ATTRIBUTE_MAX_OCCURS =4,
ATTRIBUTE_FORM =5,
ATTRIBUTE_BASE =6,
ATTRIBUTE_USE =7,
ATTRIBUTE_NAMESPACE =8,
ATTRIBUTE_PROC_CONTENTS =9,
ATTRIBUTE_VALUE =10,
ATTRIBUTE_NILLABLE =11,
ATTRIBUTE_ITEM_TYPE =12,
ATTRIBUTE_MEMBER_TYPES =13,
ATTRIBUTE_MIXED =14,
ATTRIBUTE_SCHEMA_LOCATION =15,
ATTRIBUTE_SUBSTITUTION_GROUP =16,
ATTRIBUTE_ABSTRACT =17,
ATTRIBUTE_CONTEXT_ARRAY_SIZE =18
};
typedef enum AttrEnum AttrEnum;
/** Namespace and prefix defined in a XML schema file */
struct PfxNsEntry
{
String pfx;
String ns;
};
typedef struct PfxNsEntry PfxNsEntry;
/** An array of namespaces and prefixes defined in a XML schema file */
struct PfxNsTable
{
DynArray dynArray;
PfxNsEntry *pfxNs;
Index count;
};
typedef struct PfxNsTable PfxNsTable;
/** The possible values of the schema attributes:
* elementFormDefault and attributeFormDefault */
enum FormType
{
QUALIFIED =0,
UNQUALIFIED =1
};
typedef enum FormType FormType;
/** uri/ln indices (QNameID) of an element in the string tables and the associated grammar index */
struct QNameIDGrIndx
{
QNameID qnameId;
Index grIndex;
};
typedef struct QNameIDGrIndx QNameIDGrIndx;
/**
* A TreeTableEntry in particular TreeTable
* It is defined from which XML Schema file (TreeTable) it comes from */
struct QualifiedTreeTableEntry
{
struct TreeTable* treeT;
struct TreeTableEntry* entry;
};
typedef struct QualifiedTreeTableEntry QualifiedTreeTableEntry;
/**
* Represents a single definition (i.e XML element) from the XML schema.
* For example:
* [element] entry, [complexType], [attribute] entry etc.
* The entry contains all the attribute values defined as well as
* links to nested entries, parent entries and sibling entries.
* */
struct TreeTableEntry
{
/** Child element. It is either a nested element or a link to a global definition.
* The global definition is linked during resolveTypeHierarchy(). In this case
* a local entry with type="..." (or ref="...") attribute is linked to a
* global entry that defines the corresponding type or referenced element.
* The linked global entry can be located in different tree (XSD file); */
QualifiedTreeTableEntry child;
/** Next element in group. For example the
* [element], [attribute], [sequence] are often sibling definitions in a complex type */
struct TreeTableEntry* next;
/** Element corresponding to a supertype.
* In case of [extension] or [restriction] entries, this pointer links the
* base type to the corresponding global type definition.
* The linked global entry can be located in different tree (XSD file); */
QualifiedTreeTableEntry supertype;
/** The XML schema element. Represented with the codes defined above */
ElemEnum element;
/** In case of attributes that are part of the definition, their values are stored as a string
* in this array. The index is the code of the attribute whose value is stored. */
String attributePointers[ATTRIBUTE_CONTEXT_ARRAY_SIZE];
/**
* Loops occur in the XSD due to <xs:element ref="element-containing-recursive-declaration" ...>
* in a complex type. When the code in treeTableToGrammars.c handleElementEl() starts processing such element it has to perform two things:
* 1) create a grammar production SE(qname)
* 2) link the grammar that describes this element to that production.
* When such grammar does not exists it tries to build it. But in order to build it it ends up at the same <xs:element ref="element-containing-recursive-declaration" ...>
* due to the recursive declaration.
* The idea to solve it: break the second try to process the complex type that contains
* <xs:element ref="element-containing-recursive-declaration" ...>
* loopDetection == 0 -> the first time the TreeTableEntry is processed
* loopDetection == INDEX_MAX -> the TreeTableEntry was processed once
* 0 < loopDetection < INDEX_MAX -> GrammarIndex of the Grammar table for complex grammar
*/
Index loopDetection;
};
typedef struct TreeTableEntry TreeTableEntry;
/**
* Tree structure to store parsed schema structure and attributes; a schema tree.
* All the information from the XML schema needed for the grammar generation is stored
* in this structure. */
struct TreeTable
{
DynArray dynArray;
TreeTableEntry* tree;
Index count;
struct
{
/** targetNamespace for that TreeTable */
String targetNs;
/** Identifies the target namespace in the EXIP Schema URI Table */
SmallIndex targetNsId;
/** Qualify namespace for locally declared elements? */
FormType elemFormDefault;
/** Qualify namespace for locally declared attributes? */
FormType attrFormDefault;
/** Namespace prefix/URI pairs */
PfxNsTable pfxNsTable;
} globalDefs;
AllocList memList; // Holding the memory allocations for the TreeTable
#if HASH_TABLE_USE
/**
* Used for fast lookups of global types when linking types' base types (extensions & restrictions)
* and element types to global types.
*/
struct hashtable* typeTbl;
/**
* Used for fast lookups of elements when linking element declarations
* referred with the ref schema attribute.
*/
struct hashtable* elemTbl;
/**
* Used for fast lookups of global attributes when linking references to global attributes
*/
struct hashtable* attrTbl;
/**
* Used for fast lookups of global model groups during linking references to them
*/
struct hashtable* groupTbl;
/**
* Used for fast lookups of global attribute groups when linking references to global attribute groups
*/
struct hashtable* attrGroupTbl;
#endif
};
typedef struct TreeTable TreeTable;
/**
* Some schema attributes (e.g. namespace="...")
* define a list of namespaces that are stored as a string.
* The string needs to be parsed and each namespace added
* as an entry in the NsTable dynamic array.
* The entries are then used to fill the URI partition
* of the string table and by the createWildcardTermGrammar()
* and createComplexGrammar()
* */
struct NsTable
{
DynArray dynArray;
String *base;
Index count;
};
typedef struct NsTable NsTable;
/** In case there are Substitution groups in the schema,
* this structure represents a Substitution group head. It has the
* head QName and an array of all its substitues as a pointer
* to their TreeTableEntry */
struct SubtGroupHead
{
DynArray dynArray;
QualifiedTreeTableEntry* substitutes;
Index count;
QNameID headId;
};
typedef struct SubtGroupHead SubtGroupHead;
/** In case there are Substitution groups in the schema,
* this structure sotres all Substitution group heads. */
struct SubstituteTable
{
DynArray dynArray;
SubtGroupHead* head;
Index count;
};
typedef struct SubstituteTable SubstituteTable;
/**
* @brief Initialize a TreeTable object
*
* @param[in, out] treeT a tree table container
* @return Error handling code
*/
errorCode initTreeTable(TreeTable* treeT);
/**
* @brief Destroy a TreeTable object (free the memory allocations)
*
* @param[in, out] treeT a tree table object
* @return Error handling code
*/
void destroyTreeTable(TreeTable* treeT);
/**
* @brief Performs two things: builds a treeTable and the string tables of the EXIPSchema object
*
* -# From the XML schema definitions builds an analogous treeTable
* -# Fills in the pre-populated entries in the string tables of the EXIPSchema object
*
* The pre-populated entries in the string tables are sorted in generateSchemaInformedGrammars()
* after all the treeTables are generated.
*
* The schema and treeT objects should be initialized before calling this function.
* @param[in] buffer an input buffer holding (part of) the representation of the schema
* @param[in] schemaFormat EXI, XSD, DTD or any other schema representation supported
* @param[in] opt options used for EXI schemaFormat - otherwise NULL. If options are set then they will be used
* for processing the EXI XSD stream although no options are specified in the EXI header. If there are
* options defined in the EXI header of the XSD stream then this parameter must be NULL.
* @param[out] treeT a memory representation of the XML schema definitions. Must be initialized.
* @param[out] schema partly built schema information (only the string tables) used for processing EXI streams.
* Must be initialized.
* @return Error handling code
*/
errorCode generateTreeTable(BinaryBuffer buffer, SchemaFormat schemaFormat, EXIOptions* opt, TreeTable* treeT, EXIPSchema* schema);
/**
* @brief Given a set of TreeTable instances, resolve the <include> or <import> dependencies
*
* @param[in, out] schema the EXIPSchema object
* @param[in, out] treeT a pointer to an array of tree table objects (can be RE-ALLOCED!)
* @param[in, out] count the number of tree table objects
* @param[in] loadSchemaHandler Call-back handler for loading <include>-ed or <import>-ed schema files; Can be left NULL
* if no <include> or <import> statements are used in the XML schema.
*
* @return Error handling code
*/
errorCode resolveIncludeImportReferences(EXIPSchema* schema, TreeTable** treeT, unsigned int* count,
errorCode (*loadSchemaHandler) (String* namespace, String* schemaLocation, BinaryBuffer** buffers, unsigned int* bufCount, SchemaFormat* schemaFormat, EXIOptions** opt));
/**
* @brief Links derived types to base types, elements to types and references to global elements
*
* In case of:
* -# type="..." attribute - finds the corresponding type definition and links it to the
* child pointer of that entry
* -# ref="..." attribute - finds the corresponding element definition and links it to the
* child pointer of that entry
* -# base="..." attribute - finds the corresponding type definition and links it to the
* supertype pointer of that entry
* -# substitutionGroup="..." attribute - finds the corresponding substituion group head
* and adds the head and the substitute in the SubstituteTable
*
* @param[in] schema the EXIPSchema object
* @param[in, out] treeT an array of tree table objects
* @param[in] count the number of tree table objects
* @param[in] subsTbl In case of substitutionGroups in the schema maps the heads of the
* substitutionGroups to their members
* @return Error handling code
*/
errorCode resolveTypeHierarchy(EXIPSchema* schema, TreeTable* treeT, unsigned int count, SubstituteTable* subsTbl);
/**
* @brief Given types resolved TreeTable objects that are created from a XML schema files,
* builds the EXIP grammars in the EXIPSchema object.
*
* @param[in] treeT an array of tree table objects
* @param[in] count the number of tree table objects
* @param[out] schema schema information used for processing EXI streams in schema mode
* @param[in] subsTbl In case of substitutionGroups in the schema maps the heads of the
* substitutionGroups to their members
* @return Error handling code
*/
errorCode convertTreeTablesToExipSchema(TreeTable* treeT, unsigned int count, EXIPSchema* schema, SubstituteTable* subsTbl);
/**
* @brief Given a type value encoded as QName string in the form "prefix:localname"
* derives the "namespace" part and the "local name" part.
*
* Used for the value of the "type" attribute of element and attribute use definitions
*
* @param[in] schema the EXIPSchema object
* @param[in] treeT a tree table object
* @param[in] typeLiteral the type literal
* @param[out] qname qname of the type
* @return Error handling code
*/
errorCode getTypeQName(EXIPSchema* schema, TreeTable* treeT, const String typeLiteral, QNameID* qname);
/**
* @brief Given a namespace="..." attribute containing a list of namespaces as a sting, returns an array of these namespaces
*
* This function also resolves the special values "##targetNamespace" and "##local"
*
* @param[in] treeT the tree table object
* @param[in] nsList a sting containing the space separated namespaces
* @param[out] nsTable an array of namespaces
* @return Error handling code
*/
errorCode getNsList(TreeTable* treeT, String nsList, NsTable* nsTable);
#if DEBUG_GRAMMAR_GEN == ON
/**
* @brief Print a tree table entry
*
* @param[in] treeTableEntryIn a tree table object
* @param[in] indentIdx Indent index
* @param[in] prefix prefix for the C definitions
*/
void printTreeTableEntry(TreeTableEntry* treeTableEntryIn, int indentIdx, char *prefix);
#endif
#endif /* TREETABLESCHEMA_H_ */