Class: Origami::PageTreeNode

Inherits:
Dictionary show all
Includes:
StandardObject
Defined in:
lib/origami/page.rb

Overview

Class representing a node in a Page tree.

Constant Summary

Constants included from StandardObject

StandardObject::DEFAULT_ATTRIBUTES

Constants inherited from Dictionary

Dictionary::TOKENS

Constants included from Object

Object::TOKENS

Instance Attribute Summary

Attributes included from ObjectCache

#names_cache, #strings_cache, #xref_cache

Attributes included from Object

#file_offset, #generation, #no, #objstm_offset, #parent

Instance Method Summary collapse

Methods included from StandardObject

included, #version_required

Methods inherited from Dictionary

#[], #[]=, hint_type, #merge, parse, #to_h, #to_obfuscated_str, #to_s, #transform_values, #transform_values!

Methods included from TypeGuessing

#guess_type

Methods included from FieldAccessor

#method_missing, #respond_to_missing?

Methods included from CompoundObject

#copy, #delete, #include?, #update_values, #update_values!

Methods included from ObjectCache

#rebuild_caches

Methods included from Object

#cast_to, #copy, #document, #export, included, #indirect?, #indirect_parent, #logicalize, #logicalize!, #native_type, #numbered?, parse, #post_build, #reference, #set_document, #set_indirect, skip_until_next_obj, #solve, #to_o, #to_s, #type, typeof, #version_required, #xrefs

Constructor Details

#initialize(hash = {}, parser = nil) ⇒ PageTreeNode

Returns a new instance of PageTreeNode.



304
305
306
307
308
309
# File 'lib/origami/page.rb', line 304

def initialize(hash = {}, parser = nil)
    super

    set_default_values # Ensure that basic tree fields are present.
    set_indirect(true)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Origami::FieldAccessor

Instance Method Details

#append_page(page) ⇒ Object

Append a page at the end of this node.



498
499
500
501
502
503
504
# File 'lib/origami/page.rb', line 498

def append_page(page)
    self.Kids ||= []
    self.Kids.push(page)
    self.Count += 1

    page.Parent = self
end

#clear_pagesObject

Removes all pages in the node.



483
484
485
486
# File 'lib/origami/page.rb', line 483

def clear_pages
    self.Count = 0
    self.Kids = []
end

#delete_page_at(n) ⇒ Object

Delete a page in the node at the specified position (starting from 1).

Raises:

  • (IndexError)


362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/origami/page.rb', line 362

def delete_page_at(n)
    raise IndexError, 'Page numbers are referenced starting from 1' if n < 1

    kids = self.Kids
    unless kids.is_a?(Array)
        raise InvalidPageTreeError, 'Kids must be an Array'
    end

    count = 0
    kids.each_with_index do |kid, index|
        node = kid.solve

        case node
        when Page
            count = count + 1
            if count == n
                kids.delete_at(index)
                self.Count -= 1
                return self
            end

        when PageTreeNode
            count = count + node.Count
            if count >= n
                node.delete_page_at(n - count + node.Count)
                self.Count -= 1
                return self
            end
        else
            raise InvalidPageTreeError, 'not a Page or PageTreeNode'
        end
    end

    raise IndexError, 'Out of order page index' unless count + 1 == n
end

#delete_pages_at(delete_idx, offset = 0) ⇒ Object

Delete a set of page in the node at the specified positions (starting from 0).



401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# File 'lib/origami/page.rb', line 401

def delete_pages_at(delete_idx, offset = 0)
    kids = self.Kids
    unless kids.is_a?(Array)
        raise InvalidPageTreeError, 'Kids must be an Array'
    end

    deleted = 0
    kids.delete_if.with_index do |kid, idx|
        node = kid.solve
        idx = idx + offset

        case node
        when Page
            if delete_idx.include?(idx)
                deleted += 1
                true
            else
                false
            end
        when PageTreeNode
            deleted += node.delete_pages_at(delete_idx, idx)
            false
        else
            raise InvalidPageTreeError, 'not a Page or PageTreeNode'
        end
    end
    self.Count -= deleted
    deleted
end

#each_page(browsed_nodes: [], &block) ⇒ Object

Iterate through each page of that node.



441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/origami/page.rb', line 441

def each_page(browsed_nodes: [], &block)
    return enum_for(__method__) { self.Count.to_i } unless block_given?

    if browsed_nodes.any?{|node| node.equal?(self)}
        raise InvalidPageTreeError, 'Cyclic tree graph detected'
    end

    unless self.Kids.is_a?(Array)
        raise InvalidPageTreeError, 'Kids must be an Array'
    end

    browsed_nodes.push(self)

    unless self.Count.nil?
        [ self.Count.value, self.Kids.length ].min.times do |n|
            node = self.Kids[n].solve

            case node
            when PageTreeNode then node.each_page(browsed_nodes: browsed_nodes, &block)
            when Page then yield(node)
            else
                raise InvalidPageTreeError, 'not a Page or PageTreeNode'
            end
        end
    end

    self
end

#get_page(n) ⇒ Object

Get the n-th Page object in this node, starting from 1.

Raises:

  • (IndexError)


473
474
475
476
477
478
# File 'lib/origami/page.rb', line 473

def get_page(n)
    raise IndexError, 'Page numbers are referenced starting from 1' if n < 1
    raise IndexError, 'Page not found' if n > self.Count.to_i

    self.each_page.lazy.drop(n - 1).first or raise IndexError, 'Page not found'
end

#insert_page(n, page) ⇒ Object

Inserts a page into the node at a specified position (starting from 1).

Raises:

  • (IndexError)


320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
# File 'lib/origami/page.rb', line 320

def insert_page(n, page)
    raise IndexError, 'Page numbers are referenced starting from 1' if n < 1

    kids = self.Kids
    unless kids.is_a?(Array)
        raise InvalidPageTreeError, 'Kids must be an Array'
    end

    count = 0
    kids.each_with_index do |kid, index|
        node = kid.solve

        case node
        when Page
            count = count + 1
            if count == n
                kids.insert(index, page)
                page.Parent = self
                self.Count += 1
                return self
            end

        when PageTreeNode
            count = count + node.Count
            if count >= n
                node.insert_page(n - count + node.Count, page)
                self.Count += 1
                return self
            end
        else
            raise InvalidPageTreeError, 'not a Page or PageTreeNode'
        end
    end

    raise IndexError, 'Out of order page index' unless count + 1 == n

    self.append_page(page)
end

#pagesObject

Returns an Array of Pages inheriting this tree node.



434
435
436
# File 'lib/origami/page.rb', line 434

def pages
    self.each_page.to_a
end

#pages?Boolean

Returns true unless the node is empty.

Returns:



491
492
493
# File 'lib/origami/page.rb', line 491

def pages?
    self.each_page.size > 0
end

#pre_buildObject

:nodoc:



311
312
313
314
315
# File 'lib/origami/page.rb', line 311

def pre_build #:nodoc:
    self.Count = self.pages.count

    super
end