## # # Copyright 2004-2006, AllAfrica Global Media # # This file is part of XML::Comma # # XML::Comma is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # any later version. # # This program 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 # GNU General Public License for more details. # # For more information about XML::Comma, point a web browser at # http://xml-comma.org, or read the tutorial included # with the XML::Comma distribution at docs/guide.html # ## package XML::Comma::Bootstrap; use XML::Comma::Util qw( dbg trim ); @ISA = ( 'XML::Comma::Def' ); use vars '$AUTOLOAD'; use strict; ## # All elements in the bootstrapping document definition are defined as # Bootstrap elements. A Bootstrap element has no def, and because of # this there is some hard-coding to determine, for example, whether a # Bootstrap element is nested or not. The basic assumption, here, is # that there are no mistakes (and so no need to validate or # differentiate much between elements of) the bootstrap_block. # # Because bootstrap elements can either have content or be nested, the # Bootstrap class is a hybrid, of sorts. It inherits NestedElement # methods via Def, but also provides its own simple content get and # set methods. # block || tag_up_path sub new { my ( $class, %arg ) = @_; if ( $arg{block} ) { my $bootstrap = eval { XML::Comma->parser()->new ( block => $arg{block}, top_level_class => $class ); }; if ( $@ ) { die "Error while defining bootstrap definition: $@"; } return $bootstrap; } my $self = {}; bless ( $self, $class ); $self->_init ( def => '', tag_up_path => $arg{tag_up_path} || 'DocumentDefinition', init_index => $arg{init_index} ); return $self; } sub finish_initial_read { my ( $self, $in_progress_parser ) = @_; # only add_def for top-level and element blocks, and only set and # trim the content for the rest (a little cheating is okay in a # bootstrap module, right?) my $tag = $self->tag(); if ( $tag eq 'DocumentDefinition' or $tag eq 'element' or $tag eq 'nested_element' ) { $self->_Def_init_name_up_path ( $in_progress_parser ); XML::Comma::DefManager->add_def ( $self ); $self->_config_dispatcher(); } else { $self->{_Bootstrap_content} = trim ( $self->{_Bootstrap_content} ); } } # bootstrap is a hybrid -- it's a def/nested-element, but it also has # basic raw_append and get. sub raw_append { $_[0]->{_Bootstrap_content} .= $_[1]; } sub get { return $_[0]->{_Bootstrap_content} || ''; } # override the standard Def::add_element to not do a defined check, and to # instantiate all children as Bootstraps, too. sub add_element { my ( $self, $tag ) = @_; my $element = ref($self)->new ( tag_up_path => $self->tag_up_path() . ':' . $tag, init_index => scalar(@{$self->{_nested_elements}}) ); $self->_add_elements ( $element ); return $element; } # override the standard Element::_init_def to not do anything about defs sub _init_def { } # a little hard-coding to handle whether we are defining a nested # element or not. getting these wrong breaks everything else, # sometimes in non-intuitive ways. sub is_nested { my $tag = $_[0]->tag(); return 1 if ( $tag eq 'DocumentDefinition' or $tag eq 'nested_element' or $tag eq 'method' ); return 0; # this must be return 0 (not bare return). looks like # something in parser->handle_element gets mis-aligned or # something if this is 'return', but I can't find # it. (blech. yuck. how could you write such bad code?) } sub validate_content { return; } #### # AUTOLOAD # # #### sub AUTOLOAD { $AUTOLOAD =~ /::(\w+)$/; my $m = $1; die "Bootstrap should never autoload -- '$m'\n"; } sub bootstrap_block { return <<'END'; DocumentDefinition name ignore_for_hash include_for_hash plural required properties ignore_for_hash include_for_hash plural required nested blob enum boolean range timestamp timestamp_created timestamp_last_modified doc_key single_line class module config macro read_hook validate_hook document_write_hook def_hook sort_sub method name code 'name','code' element name ignore_for_hash include_for_hash class DocumentDefinition:class method DocumentDefinition:method def_hook read_hook validate_hook set_hook default macro defname sort_sub escapes escape_code unescape_code auto 'class', 'def_hook', 'read_hook', 'method', 'validate_hook', 'set_hook', 'macro' 'name' blob_element name ignore_for_hash include_for_hash class DocumentDefinition:class method DocumentDefinition:method extension def_hook validate_hook macro read_hook set_hook set_from_file_hook defname 'class', 'def_hook', 'validate_hook', 'read_hook', 'method', 'macro', 'set_hook', 'set_from_file_hook' 'name' nested_element name defname ignore_for_hash include_for_hash class DocumentDefinition:class def_hook read_hook macro plural required validate_hook sort_sub element DocumentDefinition:element blob_element DocumentDefinition:blob_element nested_element DocumentDefinition:nested_element method DocumentDefinition:method 'class', 'def_hook', 'read_hook', 'macro', 'plural', 'required', 'validate_hook', 'element', 'blob_element', 'nested_element', 'method', 'name' store name location output root base file_permissions 664 pre_store_hook post_store_hook erase_hook index_on_store qw( location output pre_store_hook post_store_hook erase_hook index_on_store ) 'name','base','location' index name store index_from_store doc_id_sql_type VARCHAR(255) field name code sql_type VARCHAR(255) 'name' collection name code type binary table sql_type VARCHAR(245) field name sql_type VARCHAR(245) clean to_size order_by size_trigger erase_where_clause 'name' sort name code type many tables clean DocumentDefinition:index:collection:clean 'name' textsearch name which_preprocessor sub { return 'XML::Comma::Pkg::Textsearch::Preprocessor_En'; } defer_on_update 'name' sql_index name unique fields 'name','fields' default_order_by doc_id order_by_expression name expression 'name','expression' clean to_size order_by size_trigger erase_where_clause index_hook stop_rebuild_hook method DocumentDefinition:method qw( index_from_store field collection bcollection sort textsearch sql_index order_by_expression index_hook stop_rebuild_hook method ) 'name' 'element', 'nested_element', 'blob_element', 'method', 'macro', 'class', 'store', 'index', 'read_hook', 'document_write_hook', 'plural', 'required', 'validate_hook', END } 1;