Ogólne#
Traversal#
W tym miejscu umieszczam powtarzające się specyficzne pojęcia i algorytmy w dziale TRAVERSAL, czyli mogą mieć one zastosowanie dla wszystkich interfejsów z tego działu.
Pojęcia#
Obiekty typu NodeIterator
oraz TreeWalker
mogą zostać użyte do filtracji oraz przechodzenia po węzłach w drzewie węzłów.
active flag
Każdy obiekt typu NodeIterator
oraz TreeWalker
ma przypisaną flagę aktywności # (active flag) zapobiegającą rekursywnym wywołaniom. Jest ona domyślnie nieaktywna (kwestia nierozstrzygnięta).
root
whatToShow
filter
Każdy obiekt typu NodeIterator
oraz TreeWalker
jest także skojarzony z węzłem będącym korzeniem # (root), maską bitów # (whatToShow) oraz zwrotnym filtrem # (filter).
iterator collection
Każdy obiekt typu NodeIterator
jest skojarzony z kolekcją iteratora # (iterator collection), która jest kolekcją zakorzenioną na korzeniu z filtrem pasującym do każdego węzła.
Algorytmy#
pre-removing steps
Kroki przed-usuwania # (pre-removing steps) węzła toBeRemovedNode z iteratora węzłowego nodeIterator są następujące:
Kroki te będą używane przez ogólny algorytm usuwania węzła, który musi sprawdzić, czy usuwany węzeł może mieć wpływ na stan wszystkich iteratorów węzłowych (opis teoretyczny).
- Jeśli toBeRemovedNode nie jest przodkiem obejmującym dla wartości atrybutu
referenceNode
w nodeIterator, to pomiń kolejne kroki. Jeśli wartością atrybutu
pointerBeforeReferenceNode
w nodeIterator jest boolowskietrue
to uruchom poniższe podkroki:- Niech next będzie pierwszym węzłem następującym dla toBeRemovedNode, który jest potomkiem obejmującym dla korzenia w nodeIterator i nie jest potomkiem obejmującym dla toBeRemovedNode, lub wartością
null
jeśli nie będzie takiego węzła. - Jeśli next nie jest wartością
null
, to ustaw atrybutreferenceNode
w nodeIterator na next i pomiń kolejne kroki. W przeciwnym razie ustaw wartość atrybut
pointerBeforeReferenceNode
w nodeIterator na boolowskefalse
.W tym momencie kolejne kroki nie zostają przerwane.
- Niech next będzie pierwszym węzłem następującym dla toBeRemovedNode, który jest potomkiem obejmującym dla korzenia w nodeIterator i nie jest potomkiem obejmującym dla toBeRemovedNode, lub wartością
- Ustaw atrybut
referenceNode
w nodeIterator na potomka obejmującego dla ostatniego (zgodnie z porządkiem drzewa) brata poprzedzającego względem toBeRemovedNode, jeśli brat poprzedzający dla toBeRemovedNode nie jest wartościąnull
, w przeciwnym razie na rodzica w toBeRemovedNode.
filter
Aby przefiltrować # (filter) węzeł node należy wykonać następujące kroki:
- Jeśli flaga aktywności jest ustawiona, to zrzuć wyjątek
"InvalidStateError"
. - Niech n będzie wartością atrybutu
nodeType
w node minus1
. - Jeśli n-ty bit (gdzie
0
jest najmniej znaczącym bitem) w masce bitowej nie jest ustawiony, to zwróćFILTER_SKIP
. - Jeśli filtr ma wartość
null
, to zwróćFILTER_ACCEPT
. - Ustaw flagę aktywności.
- Niech result będzie wartością zwracaną przez wywołanie metody
acceptNode()
w filtrze, gdzie node jest pierwszym przekazanym argument. - Usuń flagę aktywności.
- Jeśli jakiś wyjątek został zrzucony, to ponownie zrzuć wyjątek.
- Zwróć result.
traverse
Aby przejść # (traverse) w kierunku direction należy wykonać następujące kroki:
- Niech node będzie wartością atrybutu
referenceNode
w obiekcie kontekstu. - Niech before node będzie wartością atrybutu
pointerBeforeReferenceNode
w obiekcie kontekstu. - Wykonaj poniższe podkroki:
- Jeśli direction jest następujący
Jeśli before node ma boolowską wartość
false
, to ustaw node na pierwszy węzeł następujący po node w kolekcji iteratora skojarzonej z obiektem kontekstu. Jeśli nie będzie takiego węzła, to zwróć wartośćnull
.Jeśli before node ma boolowską wartość
true
, to ustaw go na boolowską wartośćfalse
.- Jeśli direction jest poprzedzający
Jeśli before node ma boolowską wartość
true
, to ustaw node na pierwszy węzeł poprzedzający przed node w kolekcji iteratora skojarzonej z obiektem kontekstu. Jeśli nie będzie takiego węzła, to zwróć wartośćnull
.Jeśli before node ma boolowską wartość
false
, to ustaw go na boolowską wartośćtrue
.
- Przefiltruj node i niech result będzie zwracaną wartością.
Jeśli result ma wartość
FILTER_ACCEPT
, to idź do następnego kroku w ogólnym zestawie kroków.W przeciwnym razie uruchom te podkroki ponownie.
- Ustaw wartość atrybutu
referenceNode
w obiekcie kontekstu na node, ustaw wartość atrybutupointerBeforeReferenceNode
w obiekcie kontekstu na before node i zwróć node.
traverse children
Aby przejść przez dzieci # (traverse children) z typem type należy wykonać następujące kroki:
- Niech node będzie wartością atrybutu
currentNode
w obiekcie kontekstu. - Ustaw node na pierwsze dziecko w node jeśli type to pierwszy, i ostatnie dziecko w node jeśli type to ostatni.
- Jeśli node ma wartość
null
, to zwróć wartośćnull
. Główna #: Wykonuj poniższe podkroki:
- Przefiltruj node i niech result będzie zwracaną wartością.
- Jeśli result ma wartość
FILTER_ACCEPT
, to ustaw atrybutcurrentNode
w obiekcie kontekstu na node i zwróć node. Jeśli result ma wartość
FILTER_SKIP
, to uruchom wewnętrzne podkroki:- Niech child będzie pierwszym dzieckiem w node jeśli type to pierwszy, i ostatnim dzieckiem w node jeśli type to ostatni.
- Jeśli child nie ma wartości
null
, to ustaw node na child i przejdź do (goto) Główna.
Powtarzaj poniższe wewnętrzne podkroki:
- Niech sibling będzie bratem następującym względem node jeśli type to pierwszy, i bratem poprzedzającym jeśli type to ostatni.
- Jeśli sibling nie ma wartości
null
, to ustaw node na sibling i przejdź do (goto) Główna. - Niech parent będzie rodzicem w node.
- Jeśli parent ma wartość
null
, parent jest korzeniem skojarzonym z obiektem kontekstu, lub parent jest wartością atrybutucurrentNode
w obiekcie kontekstu, to zwróć wartośćnull
. - W przeciwnym razie ustaw node na parent.
traverse siblings
Aby przejść przez braci # (traverse siblings) z typem type należy wykonać następujące kroki:
- Niech node będzie wartością atrybutu
currentNode
w obiekcie kontekstu. - Jeśli node jest korzeniem skojarzonym z obiektem kontekstu, to zwróć wartości
null
. Wykonaj poniższe podkroki:
- Niech sibling będzie bratem następującym względem node jeśli type to następujący, i bratem poprzedzającym jeśli type to poprzedzający.
Dopóki (while) sibling nie ma wartości
null
, to uruchom wewnętrzne podkroki:- Ustaw node na sibling.
- Przefiltruj node i niech result będzie zwracaną wartością.
- Jeśli result ma wartość
FILTER_ACCEPT
, to ustaw atrybutcurrentNode
w obiekcie kontekstu na node i zwróć node. - Ustaw sibling na pierwsze dziecko w node jeśli type to następujący, i ostatnie dziecko w node jeśli type to poprzedzający.
- Jeśli result ma wartość
FILTER_REJECT
lub sibling ma wartośćnull
, to ustaw sibling na brata następującego względem node jeśli type to następujący, i brata poprzedzającego jeśli type to poprzedzający.
- Ustaw node na swojego rodzica.
- Jeśli node ma wartość
null
lub jest korzeniem skojarzonym z obiektem kontekstu, to zwróć wartośćnull
. - Przefiltruj node i jeśli zwracaną wartością jest
FILTER_ACCEPT
, to zwróć wartośćnull
. - Uruchom te podkroki ponownie.