# encoding: utf-8
=begin

* Name: SiSU

** Description: documents, structuring, processing, publishing, search
*** document abstraction

** Author: Ralph Amissah
  <ralph@amissah.com>
  <ralph.amissah@gmail.com>

** Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
  2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Ralph Amissah,
  All Rights Reserved.

** License: GPL 3 or later:

  SiSU, a framework for document structuring, publishing and search

  Copyright (C) Ralph Amissah

  This program 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 3 of the License, or (at your option)
  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.

  You should have received a copy of the GNU General Public License along with
  this program. If not, see <http://www.gnu.org/licenses/>.

  If you have Internet connection, the latest version of the GPL should be
  available at these locations:
  <http://www.fsf.org/licensing/licenses/gpl.html>
  <http://www.gnu.org/licenses/gpl.html>

  <http://www.sisudoc.org/sisu/en/manifest/gpl.fsf.html>

** SiSU uses:
  * Standard SiSU markup syntax,
  * Standard SiSU meta-markup syntax, and the
  * Standard SiSU object citation numbering and system

** Hompages:
  <http://www.jus.uio.no/sisu>
  <http://www.sisudoc.org>

** Git
  <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=summary>
  <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=blob;f=lib/sisu/current/ao_doc_objects.rb;hb=HEAD>

=end
module SiSU_AO_DocumentStructure
  class Extract
    def extract(h,o)
      h ? h : o
    end
  end
  class ObjectMetadata
    attr_accessor :is,:of,:tags,:obj,:digest
    def initialize
      @tags={}
      @is=@tmp=@digest=nil
      @of=:meta
    end
    def metadata(tags)
      of      = @of                                                                 #Symbol, classification - group
      is      = :meta                                                               #Symbol, classification - specific type
      tags    = tags            || ((defined? o.tags)      ? o.tags        : {})    #String, metadata type/tag
      obj     = nil
      @of,@is,@tags,@obj=of,is,tags,obj
      self
    end
  end
  class ObjectMeta
    attr_accessor :obj,:is,:of,:tag,:digest,:tmp
    def initialize
      @is=@obj=@tag=@digest=@digest=@tmp=nil
      @of=:meta
    end
    def metadata(h,o=nil)
      of      = @of                                                                 #Symbol, classification - group
      is      = :meta                                                               #Symbol, classification - specific type
      tag     = h[:tag]         || ((defined? o.tag)       ? o.tag         : nil)   #String, metadata type/tag
      obj     = h[:obj]         || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      tmp     = h[:tmp]         || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      digest  = h[:digest]      || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      @of,@is,@tag,@obj,@digest,@tmp=of,is,tag,obj,digest,tmp
      self
    end
  end
  class ObjectHeading
    attr_accessor :obj,:is,:tags,:of,:lv,:ln,:lc,:use_,:name,:idx,:ocn,:odv,:osp,:node,:parent,:ocn_,:note_,:autonum_,:digest,:tmp
    def initialize
      @of=:para
      @is=@obj=@lv=@ln=@lc=@use_=@name=@idx=@size=@ocn=@odv=@osp=@node=@parent=@ocn_=@note_=@autonum_=@digest=@tmp=nil
      @tags=[]
    end
    def heading_ln(lv)
      case lv
      when /A/ then 0
      when /B/ then 1
      when /C/ then 2
      when /D/ then 3
      when /1/ then 4
      when /2/ then 5
      when /3/ then 6
      when /4/ then 7
      when /5/ then 8
      when /6/ then 9
      end
    end
    def heading_lv(ln)
      case ln.to_s
      when /0/ then 'A'
      when /1/ then 'B'
      when /2/ then 'C'
      when /3/ then 'D'
      when /4/ then '1'
      when /5/ then '2'
      when /6/ then '3'
      when /7/ then '4'
      when /8/ then '5'
      when /9/ then '6'
      end
    end
    def heading(h,o=nil)
      if not h[:ln] \
      and (h[:lv] and h[:lv]=~/[1-6A-D]/)
        h[:ln]=heading_ln(h[:lv])
      elsif not h[:lv] \
      and (h[:ln] and h[:ln].to_s=~/[0-9]/)
        h[:lv]=heading_lv(h[:ln])
      end
      of      = @of                                                                 #Symbol, classification - group
      is      = :heading                                                            #Symbol, classification - specific type
      name    = h[:name]        || ((defined? o.name)      ? o.name        : nil)   #String, named object?
      tags    = h[:tags]        || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      obj     = h[:obj]         || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx     = h[:idx]         || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn     = h[:ocn]         || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv     = h[:odv]         || ((defined? o.odv)       ? o.odv         : nil)
      osp     = h[:osp]         || ((defined? o.osp)       ? o.osp         : nil)
      node    = h[:node]        || ((defined? o.node)      ? o.node        : nil)   #[Node relationship doc structure info]
      parent  = h[:parent]      || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      lv      = h[:lv]          || ((defined? o.lv)        ? o.lv          : nil)   #Alpha-numeric, document structure as used in markup, A-D then 1-6
      ln      = h[:ln]          || ((defined? o.ln)        ? o.ln          : nil)   #Integer, document structure level, for convenience in processing 1-9
      lc      = h[:lc]          || ((defined? o.lc)        ? o.lc          : nil)   #Integer, document structure collapsed level, convenience (collapse sisu's dual level document structure for markup with simple linear structure)
      use_    = if lv \
        and lv == '1'
          h[:use_]              || ((defined? o.use_)      ? o.use_        : :ok)
        elsif not lv.empty? \
        and lv =~ /[A-D2-3]/
          :ok
        else
           h[:use_]             || ((defined? o.use_)      ? o.use_        : :ok)
        end
      ocn_    = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
        else                       h[:ocn_]
        end
      autonum_ = if h[:autonum_].nil?
                                   ((defined? o.autonum_)  ? o.autonum_    : true)  #Bool? auto-numbering if requested default on, false suppresses
        else                       h[:autonum_]
        end
      note_   = h[:note_]       || ((defined? o.note_)     ? o.note_       : false) #Bool, endnotes/footnotes? (processing optimization)
      digest  = h[:digest]      || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp     = h[:tmp]         || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@lv,@ln,@lc,@name,@tags,@obj,@idx,@ocn,@odv,@osp,@node,@parent,@use_,@ocn_,@note_,@autonum_,@digest,@tmp=
      of, is, lv, ln, lc, name, tags, obj, idx, ocn, odv, osp, node, parent, use_, ocn_, note_, autonum_, digest, tmp
      self
    end
    def heading_insert(h,o=nil)
      heading(h,o=nil)
      @is     = :heading_insert                                                     #String, classification - specific type
      self
    end
  end
  class ObjectPara
    attr_accessor :obj,:is,:tags,:of,:name,:idx,:quote_,:bullet_,:indent,:hang,:ocn,:odv,:osp,:parent,:note_,:image_,:ocn_,:digest,:tmp
    def initialize
      @of=:para
      @is=@obj=@name=@idx=@quote_=@bullet_=@indent=@hang=@size=@ocn=@odv=@osp=@parent=@note_=@image_=@ocn_=@digest=@tmp=nil
      @tags=[]
    end
    def paragraph(h,o=nil)
      of      = @of                                                                 #Symbol, classification - group
      is      = :para                                                               #Symbol, classification - specific type
      name    = h[:name]        || ((defined? o.name)      ? o.name        : nil)   #String, named object?
      tags    = h[:tags]        || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      obj     = h[:obj]         || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx     = h[:idx]         || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn     = h[:ocn]         || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv     = h[:odv]         || ((defined? o.odv)       ? o.odv         : nil)
      osp     = h[:osp]         || ((defined? o.osp)       ? o.osp         : nil)
      parent  = h[:parent]      || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      indent  = h[:indent].to_s || ((defined? o.indent)    ? o.indent.to_s : nil)   #Integer, indent level
      hang    = h[:hang].to_s   || ((defined? o.hang)      ? o.hang.to_s   : nil)   #Integer, hanging indent level
      bullet_ = h[:bullet_]     || ((defined? o.bullet_)   ? o.bullet_     : false) #Bool, bulleted?
      quote_  = h[:quote_]      || ((defined? o.quote_)    ? o.quote_      : false) #Bool, quote (blockquote)?
      note_   = h[:note_]       || ((defined? o.note_)     ? o.note_       : false) #Bool, endnotes/footnotes? (processing optimization)
      image_  = h[:image_]      || ((defined? o.image_)    ? o.image_      : false) #Bool, images? (processing optimization)
      ocn_    = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else         h[:ocn_]
      end
      digest  = h[:digest]      || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp     = h[:tmp]         || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@name,@tags,@obj,@indent,@hang,@bullet_,@quote_,@idx,@ocn,@odv,@osp,@parent,@image_,@note_,@ocn_,@digest,@tmp=
      of, is, name, tags, obj, indent, hang, bullet_, quote_, idx, ocn, odv, osp, parent, image_, note_, ocn_, digest, tmp
      self
    end
    def docinfo(h,o=nil)
      of      = @of                                                                 #String, classification - group
      is      = :docinfo                                                            #String, classification - specific type
      name    = h[:name]        || ((defined? o.name)      ? o.name        : nil)   #String, named object?
      tags    = h[:tags]        || ((defined? o.tags)      ? o.tags        : nil)   #Array, associated object tags, names if any
      obj     = h[:obj]         || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx     = nil                                                                 #String, book index provided?
      ocn     = nil                                                                 #Integer, sequential on substantive-content objects
      odv     = h[:odv]         || ((defined? o.odv)       ? o.odv         : nil)
      osp     = h[:osp]         || ((defined? o.osp)       ? o.osp         : nil)
      parent  = h[:parent]      || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      indent  = nil                                                                 #Integer, indent level
      hang    = nil                                                                 #Integer, indent level
      bullet_ = false                                                               #Bool, bulleted?
      note_   = false                                                               #Bool, endnotes/footnotes? (processing optimization)
      image_  = h[:image_]      || ((defined? o.image_)    ? o.image_      : false) #Bool, images? (processing optimization)
      ocn_    = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else                         h[:ocn_]
      end
      digest  = h[:digest]      || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp     = h[:tmp]         || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@name,@tags,@obj,@indent,@hang,@bullet_,@idx,@ocn,@odv,@osp,@parent,@image_,@note_,@ocn_,@digest,@tmp=
      of, is, name, tags, obj, indent, hang, bullet_, idx, ocn, odv, osp, parent, image_, note_, ocn_, digest, tmp
      self
    end
  end
  class ObjectBlockTxt
    attr_accessor :obj,:is,:of,:tags,:lngsyn,:idx,:ocn,:odv,:osp,:parent,:note_,:number_,:ocn_,:digest,:tmp
    def initialize
      @of=:block
      @is=@obj=@lngsyn=@idx=@ocn=@odv=@osp=@parent=@note_=@number_=@ocn_=@digest=@tmp=nil
      @tags=[]
    end
    def code(h,o=nil)
      of       = @of                                                                #Symbol, classification - group #alt 'code'
      is       = :code                                                              #Symbol, classification - specific type
      tags     = h[:tags]       || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      obj      = h[:obj]        || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      lngsyn   = h[:lngsyn]     || ((defined? o.lngsyn)    ? o.lngsyn      : :txt)  #symbol, code lngsyn
      idx      = h[:idx]        || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn      = h[:ocn]        || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv      = h[:odv]        || ((defined? o.odv)       ? o.odv         : nil)
      osp      = h[:osp]        || ((defined? o.osp)       ? o.osp         : nil)
      parent   = h[:parent]     || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      number_  = h[:number_]    || ((defined? o.number_)   ? o.number_     : false) #Bool, numbered or not?
      note_    = h[:note_]      || ((defined? o.note_)     ? o.note_       : false) #Bool, endnotes/footnotes? (processing optimization)
      ocn_     = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else                         h[:ocn_]
      end
      num      = h[:num]        || ((defined? o.num)       ? o.num         : nil)
      digest   = h[:digest]     || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp      = h[:tmp]        || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@tags,@obj,@lngsyn,@idx,@ocn,@odv,@osp,@parent,@number_,@note_,@ocn_,@num,@digest,@tmp=
      of, is, tags, obj, lngsyn, idx, ocn, odv, osp, parent, number_, note_, ocn_, num, digest, tmp
      self
    end
    def box(h,o=nil)
      of       = @of                                                                #Symbol, classification - group
      is       = :box                                                               #Symbol, classification - specific type
      tags     = h[:tags]       || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      obj      = h[:obj]        || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx      = h[:idx]        || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn      = h[:ocn]        || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv      = h[:odv]        || ((defined? o.odv)       ? o.odv         : nil)
      osp      = h[:osp]        || ((defined? o.osp)       ? o.osp         : nil)
      parent   = h[:parent]     || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      note_    = h[:note_]      || ((defined? o.note_)     ? o.note_       : false) #Bool, endnotes/footnotes? (processing optimization)
      ocn_     = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else                         h[:ocn_]
      end
      num      = h[:num]        || ((defined? o.num)       ? o.num         : nil)
      digest   = h[:digest]     || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp      = h[:tmp]        || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp=
      of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp
      self
    end
    def block(h,o=nil)
      of       = @of                                                                #Symbol, classification - group
      is       = :block                                                             #Symbol, classification - specific type
      tags     = h[:tags]       || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      obj      = h[:obj]        || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx      = h[:idx]        || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn      = h[:ocn]        || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv      = h[:odv]        || ((defined? o.odv)       ? o.odv         : nil)
      osp      = h[:osp]        || ((defined? o.osp)       ? o.osp         : nil)
      parent   = h[:parent]     || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      note_    = h[:note_]      || ((defined? o.note_)     ? o.note_       : false) #Bool, endnotes/footnotes? (processing optimization)
      ocn_     = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else                         h[:ocn_]
      end
      num      = h[:num]        || ((defined? o.num)       ? o.num         : nil)
      digest   = h[:digest]     || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp      = h[:tmp]        || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp=
      of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp
      self
    end
    def group(h,o=nil)
      of       = @of                                                                #Symbol, classification - group
      is       = :group                                                             #Symbol, classification - specific type
      tags     = h[:tags]       || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      obj      = h[:obj]        || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx      = h[:idx]        || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn      = h[:ocn]        || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv      = h[:odv]        || ((defined? o.odv)       ? o.odv         : nil)
      osp      = h[:osp]        || ((defined? o.osp)       ? o.osp         : nil)
      parent   = h[:parent]     || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      note_    = h[:note_]      || ((defined? o.note_)     ? o.note_       : false) #Bool, endnotes/footnotes? (processing optimization)
      ocn_     = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else          h[:ocn_]
      end
      num      = h[:num]        || ((defined? o.num)       ? o.num         : nil)
      digest   = h[:digest]     || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp      = h[:tmp]        || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp=
      of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp
      self
    end
    def alt(h,o=nil)                                                                #see block
      of       = @of                                                                #Symbol, classification - group
      is       = :alt                                                               #Symbol, classification - specific type
      tags     = h[:tags]       || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      obj      = h[:obj]        || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx      = h[:idx]        || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn      = h[:ocn]        || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv      = h[:odv]        || ((defined? o.odv)       ? o.odv         : nil)
      osp      = h[:osp]        || ((defined? o.osp)       ? o.osp         : nil)
      parent   = h[:parent]     || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      note_    = h[:note_]      || ((defined? o.note_)     ? o.note_       : false) #Bool, endnotes/footnotes? (processing optimization)
      ocn_     = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else                         h[:ocn_]
      end
      num      = h[:num]        || ((defined? o.num)       ? o.num         : nil)
      digest   = h[:digest]     || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp      = h[:tmp]        || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp=
      of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp
      self
    end
    def verse(h,o=nil)                                                              #part of poem decide how you deal with this
      of       = @of                                                                #Symbol, classification - group
      is       = :verse                                                             #Symbol, classification - specific type
      tags     = h[:tags]       || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      obj      = h[:obj]        || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx      = h[:idx]        || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn      = h[:ocn]        || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv      = h[:odv]        || ((defined? o.odv)       ? o.odv         : nil)
      osp      = h[:osp]        || ((defined? o.osp)       ? o.osp         : nil)
      parent   = h[:parent]     || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      ocn_     = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else                         h[:ocn_]
      end
      num      = h[:num]        || ((defined? o.num)       ? o.num         : nil)
      digest   = h[:digest]     || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp      = h[:tmp]        || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@tags,@obj,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@num,@digest,@tmp=
      of, is, tags, obj, idx, ocn, odv, osp, parent, note_, ocn_, num, digest, tmp
      @h=nil
      self
    end
  end
  class ObjectTable
    attr_accessor :obj,:is,:of,:lv,:tags,:name,:idx,:indent,:hang,:size,:ocn,:num,:head_,:cols,:widths,:odv,:osp,:parent,:note_,:ocn_,:digest,:tmp
    def initialize
      @of=:block
      @is=@obj=@lv=@name=@idx=@indent=@hang=@size=@ocn,@num,@head_,@cols,@widths=@odv=@osp=@parent=@note_=@ocn_=@num=@digest=@tmp=nil
      @tags=[]
    end
    def table(h,o=nil)
      of      = @of                                                                 #Symbol, classification - group
      is      = :table                                                              #Symbol, classification - specific type
      tags    = h[:tags]        || ((defined? o.tags)      ? o.tags        : [])    #Array, associated object tags, names if any
      cols    = h[:cols]        || ((defined? o.cols)      ? o.cols        : nil)
      widths  = h[:widths]      || ((defined? o.widths)    ? o.widths      : nil)
      obj     = h[:obj]         || ((defined? o.obj)       ? o.obj         : nil)   #String, text content
      idx     = h[:idx]         || ((defined? o.idx)       ? o.idx         : nil)   #String, book index provided?
      ocn     = h[:ocn]         || ((defined? o.ocn)       ? o.ocn         : nil)   #Integer, sequential on substantive-content objects
      odv     = h[:odv]         || ((defined? o.odv)       ? o.odv         : nil)
      osp     = h[:osp]         || ((defined? o.osp)       ? o.osp         : nil)
      parent  = h[:parent]      || ((defined? o.parent)    ? o.parent      : nil)   #[Node parent]
      head_   = h[:head_]       || ((defined? o.head_)     ? o.head_       : false)
      note_   = h[:note_]       || ((defined? o.note_)     ? o.note_       : false) #Bool, endnotes/footnotes? (processing optimization)
      ocn_    = if h[:ocn_].nil?
                                   ((defined? o.ocn_)      ? o.ocn_        : true)  #Bool? no ocn, non-substantive content, do not include in toc #consider
      else                         h[:ocn_]
      end
      num     = h[:num]         || ((defined? o.num)       ? o.num         : nil)
      digest  = h[:digest]      || ((defined? o.digest)    ? o.digest      : nil)   #hash digests, sha512, sha256 or md5
      tmp     = h[:tmp]         || ((defined? o.tmp)       ? o.tmp         : nil)   #available for processing, empty after use
      @of,@is,@tags,@cols,@widths,@obj,@idx,@ocn,@odv,@osp,@parent,@head_,@note_,@ocn_,@num,@digest,@tmp=
      of, is, tags, cols, widths, obj, idx, ocn, odv, osp, parent, head_, note_, ocn_, num, digest, tmp
      self
    end
  end
  class ObjectImage
    attr_accessor :obj,:is,:of,:lv,:idx,:size,:ocn,:parent,:note_,:ocn_,:digest,:tmp
    def initialize
      @of=:image
      @is=@obj=@lv=@idx=@size=@ocn=@parent=@note_=@ocn_=@tmp=@digest=nil
      @tags=[]
    end
    def image(h,o=nil)                                                         #not yet used, and what of a paragraph containing several images, consider
      of=     @of                                                              #Symbol, classification - group
      is=     :image                                                           #Symbol, classification - specific type
      tags=   h[:tags]    || ((defined? o.tags)      ? o.tags    : [])         #Array, associated object tags, names if any
      obj=    h[:obj]     || ((defined? o.obj)       ? o.obj     : nil)        #String, text content
      size=   h[:size]    || ((defined? o.size)      ? o.size    : nil)
      idx=    h[:idx]     || ((defined? o.idx)       ? o.idx     : nil)        #String, book index provided?
      ocn=    h[:ocn]     || ((defined? o.ocn)       ? o.ocn     : nil)        #Integer, sequential on substantive-content objects
      odv=    h[:odv]     || ((defined? o.odv)       ? o.odv     : nil)
      osp=    h[:osp]     || ((defined? o.osp)       ? o.osp     : nil)
      parent= h[:parent]  || ((defined? o.parent)    ? o.parent  : nil)        #[Node parent]
      note_=  h[:note_]   || ((defined? o.note_)     ? o.note_   : false)      #Bool, endnotes/footnotes? (processing optimization)
      ocn_=if h[:ocn_].nil?
                             ((defined? o.ocn_)  ? o.ocn_    : true)           #Bool? no ocn, non-substantive content, do not include in toc #consider
      else                   h[:ocn_]
      end
      digest= h[:digest]  || ((defined? o.digest)    ? o.digest  : nil)        #hash digests, sha512, sha256 or md5
      tmp=    h[:tmp]     || ((defined? o.tmp)       ? o.tmp     : nil)        #available for processing, empty after use
      @of,@is,@tags,@obj,@size,@idx,@ocn,@odv,@osp,@parent,@note_,@ocn_,@digest,@tmp=of,is,tags,obj,size,idx,ocn,odv,osp,parent,note_,ocn_,digest,tmp
      self
    end
  end
  class ObjectStructure
    attr_accessor :obj,:tag,:node,:lv,:ln,:lc,:status,:is,:of,:tmp
    def initialize
      @of=:structure
      @is=@obj=@node=@lv=@ln=@lc=@status=@tmp=nil
    end
    def xml_dom(h,o=nil)
      of=     @of                                                              #Symbol, classification - group
      is=     :xml_dom                                                         #Symbol, classification - specific type
      obj=    h[:obj]     || ((defined? o.obj)       ? o.obj     : '')         #String, text content
      lv=     h[:lv]      || ((defined? o.lv)        ? o.lv      : nil)        #Alpha-numeric, document structure as used in markup, A-D then 1-6
      ln=     h[:ln]      || ((defined? o.ln)        ? o.ln      : nil)        #Integer, document structure level, for convenience in processing 1-9
      lc=     h[:lc]      || ((defined? o.lc)        ? o.lc      : nil)        #Integer, document structure collapsed level, convenience (collapse sisu's dual level document structure for markup with simple linear structure)
      node=   h[:node]    || ((defined? o.node)      ? o.node    : nil)        #[Node relationship doc structure info]
      status= h[:status]  || ((defined? o.status)    ? o.status  : nil)        #tag status Symbol :open or :close
      tmp=    h[:tmp]     || ((defined? o.tmp)       ? o.tmp     : nil)        #available for processing, empty after use
      @of,@is,@obj,@status,@node,@lv,@ln,@lc,@tmp=of,is,obj,status,node,lv,ln,lc,tmp
      self
    end
  end
  class ObjectFlag
    attr_accessor :obj,:is,:of,:flag,:act,:selections,:tmp
    def initialize
      @of=:flag
      @is=@obj=@flag=@act=@selections=@tmp=nil
    end
    def flag(h,o=nil)
      of=     @of                                                              #Symbol, classification - group
      is=     :flag                                                            #Symbol, classification - specific type
      obj=    nil                                                              #String, text content
      flag=   h[:flag]     || ((defined? o.flag)      ? o.flag    : nil)       #String, text content
      act=    h[:act]      || ((defined? o.act)       ? o.act     : nil)       #String, text content
      selections=    h[:selections]      || ((defined? o.selections) ? o.selections : nil)   #String, text content
      tmp=    h[:flag]     || ((defined? o.tmp)       ? o.tmp     : nil)       #available for processing, empty after use
      @of, @is,@obj,@flag,@act,@selections,@tmp=
        of,is, obj, flag, act, selections, tmp
      self
    end
    def flag_ocn(h,o=nil)
      of=     @of                                                              #Symbol, classification - group
      is=     :flag_ocn                                                        #Symbol, classification - specific type
      obj=    nil                                                              #String, text content
      flag=   h[:flag]     || ((defined? o.flag)      ? o.flag    : nil)       #String, text content
      act=    h[:act]      || ((defined? o.act)       ? o.act     : nil)       #String, text content
      selections= h[:selections] || ((defined? o.selections) ? o.selections : nil)   #String, text content
      tmp=    h[:flag]     || ((defined? o.tmp)       ? o.tmp     : nil)       #available for processing, empty after use
      @of, @is,@obj,@flag,@act,@selections,@tmp=
        of,is, obj, flag, act, selections,tmp
      self
    end
    def flag_lng(h,o=nil)
      of=     @of                                                              #Symbol, classification - group
      is=     :flag_lng
      obj=    nil                                                              #String, text content
      flag=   h[:flag]     || ((defined? o.flag)      ? o.flag    : nil)       #Symbol, :lng_on or :lng_off
      act=    h[:act]      || ((defined? o.act)       ? o.act     : nil)       #Symbol, language set to :en etc.
      selections= h[:selections] || ((defined? o.selections) ? o.selections : nil)   #String, text content
      tmp=    h[:act]     || ((defined? o.tmp)       ? o.tmp     : nil)       #available for processing, empty after use
      @of, @is,@obj,@flag,@act,@selections,@tmp=
        of,is, obj, flag, act, selections,tmp
      self
    end
  end
  class ObjectLayout
    attr_accessor :obj,:sym,:attr,:is,:is_for,:of,:from,:tmp,:num
    def initialize
      @of=:layout
      @is=@is_for=@obj=@from=@tmp=@num=nil
    end
    def break(h,f=nil)                                                         #decide how to deal with
      of=     @of                                                              #Symbol, classification - group
      is=     :break                                                           #Symbol, classification - specific type
      obj=    h[:obj]                                                          #String, text content
      from=   f
      tmp=    h[:tmp]                                                          #available for processing, empty after use
      @of,@is,@obj,@from,@tmp=of,is,obj,from,tmp
      self
    end
    def insert(h,o=nil)                                                        #decide how to deal with, could mimic paragraph?
      of=     @of                                                              #Symbol, classification - group
      is=     :insert                                                          #Symbol, classification - specific type
      obj=    h[:obj]     || ((defined? o.obj)       ? o.obj     : nil)        #String, text content
      tmp=    h[:tmp]     || ((defined? o.tmp)       ? o.tmp     : nil)        #available for processing, empty after use
      @of,@is,@obj,@tmp=of,is,obj,tmp
      self
    end
    def open_close(h,o=nil)                                                    #useful for poem & quote
      of=     @of                                                              #Symbol, classification - group
      is=     :open_close_tags                                                 #Symbol, classification - specific type
      is_for= h[:is_for]  || ((defined? o.is_for)    ? o.is_for  : nil)        #String, text content
      obj=    h[:obj]     || ((defined? o.obj)       ? o.obj     : nil)        #String, text content
      sym=    h[:sym]     || ((defined? o.sym)       ? o.sym     : nil)        #Symbol tag_open, tag_close
      attr=   h[:attr]    || ((defined? o.attr)      ? o.attr    : nil)        #String, text content
      tmp=    h[:tmp]     || ((defined? o.tmp)       ? o.tmp     : nil)        #available for processing, empty after use
      num=    h[:num]     || ((defined? o.num)       ? o.num     : nil)
      @of,@is,@is_for,@obj,@sym,@attr,@tmp,@num=
      of, is, is_for, obj, sym, attr, tmp, num
      self
    end
  end
  class ObjectComment
    attr_accessor :obj,:is,:of,:tmp
    def initialize
      @of=:comment
      @is=@obj=@tmp=nil
    end
    def comment(h,o=nil)
      of=     @of                                                              #Symbol, classification - group
      is=     :comment                                                         #Symbol, classification - specific type
      obj=    h[:obj]     || ((defined? o.obj)       ? o.obj     : nil)        #String, text content
      tmp=    h[:tmp]     || ((defined? o.tmp)       ? o.tmp     : nil)        #available for processing, empty after use
      @of,@is,@obj,@tmp=of,is,obj,tmp
      self
    end
  end
end
__END__
# ~# |-# no paragraph number # -# not included in toc
