1/*
2  Copyright (C) 2000-2005 SKYRIX Software AG
3
4  This file is part of SOPE.
5
6  SOPE is free software; you can redistribute it and/or modify it under
7  the terms of the GNU Lesser General Public License as published by the
8  Free Software Foundation; either version 2, or (at your option) any
9  later version.
10
11  SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14  License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with SOPE; see the file COPYING.  If not, write to the
18  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19  02111-1307, USA.
20*/
21
22#include <DOM/DOMNode.h>
23#include "common.h"
24
25@implementation NGDOMNodeWithChildren
26
27- (void)dealloc {
28  [self->childNodes makeObjectsPerformSelector:
29	              @selector(_domNodeForgetParentNode:)
30                    withObject:nil];
31
32  [self->childNodes release];
33  [super dealloc];
34}
35
36- (void)_ensureChildNodes {
37  if (self->childNodes == nil)
38    self->childNodes = [[NSMutableArray alloc] init];
39}
40
41- (BOOL)_isValidChildNode:(id)_node {
42  return YES;
43}
44
45/* navigation */
46
47- (id<NSObject,DOMNodeList>)childNodes {
48  [self _ensureChildNodes];
49
50  /* casting NSMutableArray to DOMNodeList */
51  return (id<NSObject,DOMNodeList>)self->childNodes;
52}
53- (BOOL)hasChildNodes {
54  return [self->childNodes count] > 0 ? YES : NO;
55}
56- (id<NSObject,DOMNode>)firstChild {
57  return [self->childNodes count] > 0
58    ? [self->childNodes objectAtIndex:0]
59    : nil;
60}
61- (id<NSObject,DOMNode>)lastChild {
62  NSUInteger count;
63
64  return (count = [self->childNodes count]) > 0
65    ? [self->childNodes objectAtIndex:(count - 1)]
66    : nil;
67}
68
69/* modification */
70
71- (id<NSObject,DOMNode>)removeChild:(id<NSObject,DOMNode>)_node {
72  NSUInteger idx;
73
74  if (self->childNodes == nil)
75    /* this node has no childnodes ! */
76    return nil;
77
78  if ((idx = [self->childNodes indexOfObject:_node]) == NSNotFound)
79    /* given node is not a child of this node ! */
80    return nil;
81
82  [[_node retain] autorelease];
83  [self->childNodes removeObjectAtIndex:idx];
84  [(id)_node _domNodeForgetParentNode:self];
85
86  return _node;
87}
88
89- (id<NSObject,DOMNode>)appendChild:(id<NSObject,DOMNode>)_node {
90  if (_node == nil)
91    /* adding a 'nil' node ?? */
92    return nil;
93
94  if ([_node nodeType] == DOM_DOCUMENT_FRAGMENT_NODE) {
95    id             fragNodes;
96    NSUInteger     i, count;
97    NSMutableArray *cache;
98
99    fragNodes = [_node childNodes];
100
101    if ((count = [fragNodes count]) == 0)
102      /* no nodes to add */
103      return nil;
104
105    /*
106       copy to cache, since 'childNodes' result is 'live' and
107       appendChild modifies the tree
108    */
109    cache = [NSMutableArray arrayWithCapacity:count];
110    for (i = 0; i < count; i++)
111      [cache addObject:[fragNodes objectAtIndex:i]];
112
113    /* append nodes (in reverse order [array implementation is assumed]) .. */
114    for (i = count = [cache count]; i > 0; i--)
115      [self appendChild:[cache objectAtIndex:(i - 1)]];
116  }
117  else {
118    id oldParent;
119
120    if ((oldParent = [_node parentNode]))
121      [oldParent removeChild:_node];
122
123    [self _ensureChildNodes];
124
125    [self->childNodes addObject:_node];
126    [(id)_node _domNodeRegisterParentNode:self];
127  }
128
129  /* return the node 'added' */
130  return _node;
131}
132
133/* sibling navigation */
134
135- (id)_domNodeBeforeNode:(id)_node {
136  NSUInteger idx;
137
138  if ((idx = [self->childNodes indexOfObject:_node]) == NSNotFound)
139    /* given node isn't a child of this node */
140    return nil;
141  if (idx == 0)
142    /* given node is the first child */
143    return nil;
144
145  return [self->childNodes objectAtIndex:(idx - 1)];
146}
147- (id)_domNodeAfterNode:(id)_node {
148  NSUInteger idx, count;
149
150  if ((count = [self->childNodes count]) == 0)
151    /* this node has no children at all .. */
152    return nil;
153
154  if ((idx = [self->childNodes indexOfObject:_node]) == NSNotFound)
155    /* given node isn't a child of this node */
156    return nil;
157  if (idx == (count - 1))
158    /* given node is the last child */
159    return nil;
160
161  return [self->childNodes objectAtIndex:(idx + 1)];
162}
163
164@end /* NGDOMNodeWithChildren */
165