2014-02-17 22:13:55 +00:00
###############################################################################
# #
# This file is part of IfcOpenShell. #
# #
# IfcOpenShell is free software: you can redistribute it and/or modify #
# it under the terms of the Lesser GNU General Public License as published by #
# the Free Software Foundation, either version 3.0 of the License, or #
# (at your option) any later version. #
# #
# IfcOpenShell is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# Lesser GNU General Public License for more details. #
# #
# You should have received a copy of the Lesser GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
###############################################################################
2017-08-04 16:29:26 +02:00
import operator
2016-02-18 13:17:15 +01:00
import codegen
2014-02-17 22:13:55 +00:00
import templates
import documentation
2016-02-18 13:17:15 +01:00
class Header ( codegen . Base ) :
2014-02-17 22:13:55 +00:00
def __init__ ( self , mapping ) :
declarations = [ ]
write = lambda str , * * kwargs : declarations . append ( str % dict ( {
' documentation ' : templates . multi_line_comment ( documentation . description ( kwargs [ ' name ' ] ) ) } , * * kwargs ) )
2015-01-05 14:11:42 +00:00
forward_names = list ( mapping . schema . entities . keys ( ) ) + list ( mapping . schema . simpletypes . keys ( ) )
forward_definitions = " " . join ( [ " class %s ; " % n for n in forward_names ] )
2014-02-17 22:13:55 +00:00
for name , type in mapping . schema . selects . items ( ) :
write ( templates . select , name = name )
for name , type in mapping . schema . enumerations . items ( ) :
short_name = name [ : - 4 ] if name . endswith ( " Enum " ) else name
write ( templates . enumeration , name = name , values = " , " . join ( [ " %s _ %s " % ( short_name , v ) for v in type . values ] ) )
2015-01-05 14:11:42 +00:00
emitted_simpletypes = set ( )
while len ( emitted_simpletypes ) < len ( mapping . schema . simpletypes ) :
for name , type in mapping . schema . simpletypes . items ( ) :
2016-04-08 23:23:29 +02:00
if name . lower ( ) in emitted_simpletypes : continue
2015-01-05 14:11:42 +00:00
type_str = mapping . make_type_string ( mapping . flatten_type_string ( type ) )
attr_type = mapping . make_argument_type ( type )
superclass = mapping . simple_type_parent ( name )
if superclass is None :
superclass = " IfcUtil::IfcBaseType "
2016-04-08 23:23:29 +02:00
elif superclass . lower ( ) not in emitted_simpletypes :
2015-01-05 14:11:42 +00:00
continue
2016-04-08 23:23:29 +02:00
else :
# Case normalize
superclass = [ k for k in mapping . schema . simpletypes . keys ( ) if k . lower ( ) == superclass . lower ( ) ] [ 0 ]
emitted_simpletypes . add ( name . lower ( ) )
2015-01-05 14:11:42 +00:00
write ( templates . simpletype , name = name , type = type_str , attr_type = attr_type , superclass = superclass )
2014-02-17 22:13:55 +00:00
class_definitions = [ ]
write = lambda str , * * kwargs : class_definitions . append ( str % dict ( {
' documentation ' : templates . multi_line_comment ( documentation . description ( kwargs [ ' name ' ] ) ) } , * * kwargs ) )
emitted_entities = set ( )
while len ( emitted_entities ) < len ( mapping . schema . entities ) :
for name , type in mapping . schema . entities . items ( ) :
2016-04-08 23:23:29 +02:00
if name . lower ( ) in emitted_entities : continue
if len ( type . supertypes ) == 0 or set ( map ( str . lower , type . supertypes ) ) < = emitted_entities :
2014-02-17 22:13:55 +00:00
attr_lines = [ ]
def write_method ( attr ) :
if attr . optional :
attr_lines . append ( templates . optional_attribute_description % ( attr . name , name ) )
2014-05-04 14:42:55 +00:00
attr_lines . append ( " bool has %s () const; " % ( attr . name ) )
2016-04-08 23:23:29 +02:00
attr_lines . extend ( [ " /// %s " % d for d in documentation . description ( " . " . join ( ( name , attr . name ) ) ) ] )
2014-02-17 22:13:55 +00:00
type_str = mapping . get_parameter_type ( attr , allow_optional = False , allow_entities = False )
if mapping . make_argument_type ( attr ) != " IfcUtil::Argument_UNKNOWN " :
2014-05-04 14:42:55 +00:00
attr_lines . append ( " %s %s () const; " % ( type_str , attr . name ) )
2014-02-17 22:13:55 +00:00
attr_lines . append ( " void set %s ( %s v); " % ( attr . name , type_str ) )
[ write_method ( attr ) for attr in type . attributes ]
inv_lines = [ ]
def write_inverse ( attr ) :
inv_lines . append ( templates . inverse_attr % { ' name ' : attr . name , ' entity ' : attr . entity , ' attribute ' : attr . attribute } )
if type . inverse :
2020-08-29 10:23:59 +02:00
[ write_inverse ( attr ) for attr in type . inverse ]
2014-02-17 22:13:55 +00:00
attributes = " \n " . join ( [ " %s %s " % ( ' ' * 4 , a ) for a in attr_lines ] )
if len ( attributes ) : attributes + = ' \n '
inverse = " \n " . join ( [ " %s %s " % ( ' ' * 4 , a ) for a in inv_lines ] )
if len ( inverse ) : inverse + = ' \n '
2016-04-08 23:23:29 +02:00
def case_norm ( n ) :
n = n . lower ( )
return [ k for k in mapping . schema . entities . keys ( ) if k . lower ( ) == n ] [ 0 ]
supertypes = map ( case_norm , type . supertypes ) if len ( type . supertypes ) else [ ' IfcUtil::IfcBaseEntity ' ]
2014-02-17 22:13:55 +00:00
superclass = " : %s " % ( " , " . join ( [ " public %s " % c for c in supertypes ] ) )
argument_count = mapping . argument_count ( type )
argument_start = argument_count - len ( type . attributes )
argument_name_function_body_switch_stmt = " switch (i) { %s } " % ( " " . join ( [ ' case %d : return " %s " ; ' % ( i + argument_start , attr . name ) for i , attr in enumerate ( type . attributes ) ] ) ) if len ( type . attributes ) else " "
2016-07-15 06:49:32 +03:00
argument_name_function_body_tail = ( " return %s ::getArgumentName(i); " % type . supertypes [ 0 ] ) if len ( type . supertypes ) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException( " Argument index out of range " ); '
2014-02-17 22:13:55 +00:00
argument_name_function_body = argument_name_function_body_switch_stmt + argument_name_function_body_tail
2017-08-04 16:29:26 +02:00
derived = mapping . derived_in_supertype ( type )
attribute_names = list ( map ( operator . attrgetter ( ' name ' ) , mapping . arguments ( type ) ) )
derived_in_supertype = set ( derived ) & set ( attribute_names )
derived_in_supertype_indices = sorted ( attribute_names . index ( nm ) for nm in derived_in_supertype )
attribute_type_cases = [ ' case %d : return IfcUtil::Argument_DERIVED; ' % idx for idx in derived_in_supertype_indices ]
attribute_type_cases + = [ ' case %d : return %s ; ' % ( i + argument_start , mapping . make_argument_type ( attr ) ) for i , attr in enumerate ( type . attributes ) ]
argument_type_function_body_switch_stmt = " switch (i) { %s } " % ( " " . join ( attribute_type_cases ) ) if len ( type . attributes ) else " "
2016-07-15 06:49:32 +03:00
argument_type_function_body_tail = ( " return %s ::getArgumentType(i); " % type . supertypes [ 0 ] ) if len ( type . supertypes ) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException( " Argument index out of range " ); '
2014-02-17 22:13:55 +00:00
argument_type_function_body = argument_type_function_body_switch_stmt + argument_type_function_body_tail
2015-02-17 19:48:41 +00:00
argument_entity_function_body_switch_stmt = " switch (i) { %s } " % ( " " . join ( [ ' case %d : return %s ; ' % ( i + argument_start , mapping . make_argument_entity ( attr ) ) for i , attr in enumerate ( type . attributes ) ] ) ) if len ( type . attributes ) else " "
2016-07-15 06:49:32 +03:00
argument_entity_function_body_tail = ( " return %s ::getArgumentEntity(i); " % type . supertypes [ 0 ] ) if len ( type . supertypes ) == 1 else ' (void)i; throw IfcParse::IfcAttributeOutOfRangeException( " Argument index out of range " ); '
2015-02-17 19:48:41 +00:00
argument_entity_function_body = argument_entity_function_body_switch_stmt + argument_entity_function_body_tail
2014-02-17 22:13:55 +00:00
constructor_arguments = " , " . join ( " %(full_type)s v %(index)d _ %(name)s " % a for a in mapping . get_assignable_arguments ( type ) )
write ( templates . entity , * * locals ( ) )
emitted_entities . add ( name )
self . str = templates . header % {
' schema_name_upper ' : mapping . schema . name . upper ( ) ,
' schema_name ' : mapping . schema . name . capitalize ( ) ,
' declarations ' : ' ' . join ( declarations ) ,
' forward_definitions ' : forward_definitions ,
' class_definitions ' : ' ' . join ( class_definitions )
}
self . schema_name = mapping . schema . name . capitalize ( )
2016-02-18 13:17:15 +01:00
self . file_name = ' %s .h ' % self . schema_name
2014-02-17 22:13:55 +00:00
def __repr__ ( self ) :
return self . str
2020-03-17 11:55:28 +01:00
Generator = Header