use std::cell::{RefCell, Ref, RefMut};
use std::rc::Rc;
use std::fmt;
use attribute::*;
use {
AttributeId,
ElementId,
Error,
Name,
NameRef,
SvgId,
TagName,
TagNameRef,
};
use super::document::Document;
use super::iterators::*;
use super::node_data::NodeData;
use super::node_type::NodeType;
macro_rules! try_opt {
($expr: expr) => {
match $expr {
Some(value) => value,
None => return None
}
}
}
impl SvgId for ElementId {
fn name(&self) -> &str { self.name() }
}
pub struct Node(pub Rc<RefCell<NodeData>>);
impl Node {
pub fn document(&self) -> Document {
Document { root: Node(self.0.borrow().doc.as_ref().unwrap().upgrade().unwrap()) }
}
pub fn parent(&self) -> Option<Node> {
Some(Node(try_opt!(try_opt!(self.0.borrow().parent.as_ref()).upgrade())))
}
pub fn has_parent(&self) -> bool {
match self.parent() {
Some(node) => node.node_type() != NodeType::Root,
None => false,
}
}
pub fn parents(&self) -> Parents {
Parents::new(self.parent())
}
pub fn children(&self) -> Children {
Children::new(self.first_child())
}
pub fn has_children(&self) -> bool {
self.first_child().is_some()
}
pub fn first_child(&self) -> Option<Node> {
Some(Node(try_opt!(self.0.borrow().first_child.as_ref()).clone()))
}
pub fn last_child(&self) -> Option<Node> {
Some(Node(try_opt!(try_opt!(self.0.borrow().last_child.as_ref()).upgrade())))
}
pub fn previous_sibling(&self) -> Option<Node> {
Some(Node(try_opt!(try_opt!(self.0.borrow().previous_sibling.as_ref()).upgrade())))
}
pub fn next_sibling(&self) -> Option<Node> {
Some(Node(try_opt!(self.0.borrow().next_sibling.as_ref()).clone()))
}
pub fn descendants(&self) -> Descendants {
Descendants::new(self)
}
pub fn traverse(&self) -> Traverse {
Traverse::new(self)
}
pub fn detach(&self) {
self.0.borrow_mut().detach();
}
pub fn remove(&self) {
Node::_remove(self);
self.detach();
}
fn _remove(node: &Node) {
let mut ids: Vec<AttributeId> = node.attributes().iter_svg()
.filter(|&(_, a)| a.is_link() || a.is_func_link())
.map(|(id, _)| id)
.collect();
for id in &ids {
node.remove_attribute(*id);
}
for linked in node.linked_nodes().collect::<Vec<Node>>() {
ids.clear();
for (aid, attr) in linked.attributes().iter_svg() {
match attr.value {
AttributeValue::Link(ref link) | AttributeValue::FuncLink(ref link) => {
if link == node {
ids.push(aid);
}
}
_ => {}
}
}
for id in &ids {
linked.remove_attribute(*id);
}
}
for child in node.children().svg() {
Node::_remove(&child);
}
}
pub fn drain<P>(&self, f: P) -> usize
where P: Fn(&Node) -> bool
{
let mut count = 0;
Node::_drain(self, &f, &mut count);
count
}
fn _drain<P>(parent: &Node, f: &P, count: &mut usize)
where P: Fn(&Node) -> bool
{
let mut node = parent.first_child();
while let Some(n) = node {
if f(&n) {
node = n.next_sibling();
n.remove();
*count += 1;
} else {
if n.has_children() {
Node::_drain(&n, f, count);
}
node = n.next_sibling();
}
}
}
pub fn make_copy(&self) -> Node {
match self.node_type() {
NodeType::Element => {
let elem = self.document().create_element(self.tag_name().unwrap().into_ref());
for attr in self.attributes().iter() {
elem.set_attribute_object(attr.clone());
}
elem
}
_ => {
self.document().create_node(self.node_type(), &*self.text())
}
}
}
pub fn make_deep_copy(&self) -> Node {
let root = self.make_copy();
Node::_make_deep_copy(&root, self);
root
}
fn _make_deep_copy(parent: &Node, node: &Node) {
for child in node.children() {
let new_node = child.make_copy();
parent.append(&new_node);
if child.has_children() {
Node::_make_deep_copy(&new_node, &child);
}
}
}
pub fn append(&self, new_child: &Node) {
let mut self_borrow = self.0.borrow_mut();
let mut last_child_opt = None;
let nc = new_child.clone();
{
let mut new_child_borrow = nc.0.borrow_mut();
new_child_borrow.detach();
new_child_borrow.parent = Some(Rc::downgrade(&self.0));
if let Some(last_child_weak) = self_borrow.last_child.take() {
if let Some(last_child_strong) = last_child_weak.upgrade() {
new_child_borrow.previous_sibling = Some(last_child_weak);
last_child_opt = Some(last_child_strong);
}
}
self_borrow.last_child = Some(Rc::downgrade(&nc.0));
}
if let Some(last_child_strong) = last_child_opt {
let mut last_child_borrow = last_child_strong.borrow_mut();
debug_assert!(last_child_borrow.next_sibling.is_none());
last_child_borrow.next_sibling = Some(nc.0);
} else {
debug_assert!(self_borrow.first_child.is_none());
self_borrow.first_child = Some(nc.0);
}
}
pub fn prepend(&self, new_child: &Node) {
let mut self_borrow = self.0.borrow_mut();
{
let mut new_child_borrow = new_child.0.borrow_mut();
new_child_borrow.detach();
new_child_borrow.parent = Some(Rc::downgrade(&self.0));
match self_borrow.first_child.take() {
Some(first_child_strong) => {
{
let mut first_child_borrow = first_child_strong.borrow_mut();
debug_assert!(first_child_borrow.previous_sibling.is_none());
first_child_borrow.previous_sibling = Some(Rc::downgrade(&new_child.0));
}
new_child_borrow.next_sibling = Some(first_child_strong);
}
None => {
debug_assert!(self_borrow.first_child.is_none());
self_borrow.last_child = Some(Rc::downgrade(&new_child.0));
}
}
}
self_borrow.first_child = Some(new_child.clone().0);
}
pub fn insert_after(&self, new_sibling: &Node) {
let mut self_borrow = self.0.borrow_mut();
{
let mut new_sibling_borrow = new_sibling.0.borrow_mut();
new_sibling_borrow.detach();
new_sibling_borrow.parent = self_borrow.parent.clone();
new_sibling_borrow.previous_sibling = Some(Rc::downgrade(&self.0));
match self_borrow.next_sibling.take() {
Some(next_sibling_strong) => {
{
let mut next_sibling_borrow = next_sibling_strong.borrow_mut();
debug_assert!({
let weak = next_sibling_borrow.previous_sibling.as_ref().unwrap();
same_rc(&weak.upgrade().unwrap(), &self.0)
});
next_sibling_borrow.previous_sibling = Some(Rc::downgrade(&new_sibling.0));
}
new_sibling_borrow.next_sibling = Some(next_sibling_strong);
}
None => {
if let Some(parent_ref) = self_borrow.parent.as_ref() {
if let Some(parent_strong) = parent_ref.upgrade() {
let mut parent_borrow = parent_strong.borrow_mut();
parent_borrow.last_child = Some(Rc::downgrade(&new_sibling.0));
}
}
}
}
}
self_borrow.next_sibling = Some(new_sibling.clone().0);
}
pub fn insert_before(&self, new_sibling: &Node) {
let mut self_borrow = self.0.borrow_mut();
let mut previous_sibling_opt = None;
{
let mut new_sibling_borrow = new_sibling.0.borrow_mut();
new_sibling_borrow.detach();
new_sibling_borrow.parent = self_borrow.parent.clone();
new_sibling_borrow.next_sibling = Some(self.0.clone());
if let Some(previous_sibling_weak) = self_borrow.previous_sibling.take() {
if let Some(previous_sibling_strong) = previous_sibling_weak.upgrade() {
new_sibling_borrow.previous_sibling = Some(previous_sibling_weak);
previous_sibling_opt = Some(previous_sibling_strong);
}
}
self_borrow.previous_sibling = Some(Rc::downgrade(&new_sibling.0));
}
if let Some(previous_sibling_strong) = previous_sibling_opt {
let mut previous_sibling_borrow = previous_sibling_strong.borrow_mut();
debug_assert!({
let rc = previous_sibling_borrow.next_sibling.as_ref().unwrap();
same_rc(rc, &self.0)
});
previous_sibling_borrow.next_sibling = Some(new_sibling.clone().0);
} else {
if let Some(parent_ref) = self_borrow.parent.as_ref() {
if let Some(parent_strong) = parent_ref.upgrade() {
let mut parent_borrow = parent_strong.borrow_mut();
parent_borrow.first_child = Some(new_sibling.clone().0);
}
}
}
}
pub fn node_type(&self) -> NodeType {
self.0.borrow().node_type
}
pub fn text(&self) -> Ref<String> {
Ref::map(self.0.borrow(), |n| &n.text)
}
pub fn text_mut(&self) -> RefMut<String> {
RefMut::map(self.0.borrow_mut(), |n| &mut n.text)
}
pub fn set_text(&self, text: &str) {
debug_assert_ne!(self.node_type(), NodeType::Element);
let mut b = self.0.borrow_mut();
b.text = text.to_owned();
}
pub fn set_id<S: Into<String>>(&self, id: S) {
debug_assert_eq!(self.node_type(), NodeType::Element);
let mut self_borrow = self.0.borrow_mut();
self_borrow.id = id.into();
}
pub fn id(&self) -> Ref<String> {
Ref::map(self.0.borrow(), |n| &n.id)
}
pub fn has_id(&self) -> bool {
!self.0.borrow().id.is_empty()
}
pub fn is_svg_element(&self) -> bool {
let b = self.0.borrow();
match b.tag_name {
Some(ref tag) => {
match *tag {
Name::Id(_) => true,
Name::Name(_) => false,
}
}
None => false,
}
}
pub fn set_tag_name<'a, T>(&self, tag_name: T)
where TagNameRef<'a>: From<T>
{
debug_assert_eq!(self.node_type(), NodeType::Element);
let tn = TagNameRef::from(tag_name);
if let NameRef::Name(name) = tn {
if name.is_empty() {
panic!("supplied tag name is empty");
}
}
let mut self_borrow = self.0.borrow_mut();
self_borrow.tag_name = Some(Name::from(tn));
}
pub fn tag_name(&self) -> Option<Ref<TagName>> {
let b = self.0.borrow();
match b.tag_name {
Some(_) => Some(Ref::map(self.0.borrow(), |n| n.tag_name.as_ref().unwrap())),
None => None,
}
}
pub fn tag_id(&self) -> Option<ElementId> {
let b = self.0.borrow();
match b.tag_name {
Some(ref t) => {
match *t {
Name::Id(ref id) => Some(*id),
Name::Name(_) => None,
}
}
None => None,
}
}
pub fn is_tag_name<'a, T>(&self, tag_name: T) -> bool
where TagNameRef<'a>: From<T>
{
let b = self.0.borrow();
match b.tag_name {
Some(ref v) => v.into_ref() == TagNameRef::from(tag_name),
None => false,
}
}
pub fn set_attribute<'a, N, T>(&self, name: N, value: T)
where AttributeNameRef<'a>: From<N>, N: Copy, AttributeValue: From<T>
{
debug_assert!(self.node_type() == NodeType::Element);
self.remove_attribute(name);
let a = Attribute::new(name, value);
let mut attrs = self.attributes_mut();
attrs.insert(a);
}
pub fn set_attribute_object(&self, attr: Attribute) {
debug_assert!(self.node_type() == NodeType::Element);
self.remove_attribute(attr.name.into_ref());
if attr.is_svg() {
match attr.value {
AttributeValue::Link(ref iri) | AttributeValue::FuncLink(ref iri) => {
let aid = attr.id().unwrap();
self.set_link_attribute(aid, iri.clone()).unwrap();
return;
}
_ => {}
}
}
let mut attrs = self.attributes_mut();
attrs.insert(attr);
}
pub fn set_link_attribute(&self, id: AttributeId, node: Node) -> Result<(), Error> {
debug_assert!(self.node_type() == NodeType::Element);
if node.id().is_empty() {
return Err(Error::ElementMustHaveAnId);
}
if *self.id() == *node.id() {
return Err(Error::ElementCrosslink);
}
{
let self_borrow = self.0.borrow();
let v = &self_borrow.linked_nodes;
if v.iter().any(|n| Node(n.upgrade().unwrap()) == node) {
return Err(Error::ElementCrosslink);
}
}
self.remove_attribute(id);
{
let a = if id == AttributeId::XlinkHref {
Attribute::new(id, AttributeValue::Link(node.clone()))
} else {
Attribute::new(id, AttributeValue::FuncLink(node.clone()))
};
let mut attributes = self.attributes_mut();
attributes.insert(a);
}
{
let mut value_borrow = node.0.borrow_mut();
value_borrow.linked_nodes.push(Rc::downgrade(&self.0));
}
Ok(())
}
pub fn attribute_value(&self, id: AttributeId) -> Option<AttributeValue> {
self.attributes().get_value(id).cloned()
}
pub fn attribute(&self, id: AttributeId) -> Option<Attribute> {
self.attributes().get(id).cloned()
}
pub fn attributes(&self) -> Ref<Attributes> {
Ref::map(self.0.borrow(), |n| &n.attributes)
}
pub fn attributes_mut(&self) -> RefMut<Attributes> {
RefMut::map(self.0.borrow_mut(), |n| &mut n.attributes)
}
#[inline]
pub fn has_attribute<'a, N>(&self, name: N) -> bool
where AttributeNameRef<'a>: From<N>
{
self.0.borrow().attributes.contains(name)
}
pub fn has_visible_attribute(&self, id: AttributeId) -> bool {
self.has_attribute(id) && self.attributes().get(id).unwrap().visible
}
pub fn has_attributes(&self, ids: &[AttributeId]) -> bool {
let attrs = self.attributes();
for id in ids {
if attrs.contains(*id) {
return true;
}
}
false
}
pub fn has_attribute_with_value<T>(&self, id: AttributeId, value: T) -> bool
where AttributeValue: From<T>
{
match self.attribute_value(id) {
Some(a) => a == AttributeValue::from(value),
None => false,
}
}
pub fn remove_attribute<'a, N>(&self, name: N)
where AttributeNameRef<'a>: From<N>, N: Copy
{
if !self.has_attribute(name) {
return;
}
let mut attrs = self.attributes_mut();
if let Some(value) = attrs.get_value(name) {
match *value {
AttributeValue::Link(ref node) | AttributeValue::FuncLink(ref node) => {
let mut self_borrow = node.0.borrow_mut();
let ln = &mut self_borrow.linked_nodes;
let index = ln.iter().position(|x| {
same_rc(&x.upgrade().unwrap(), &self.0)
}).unwrap();
ln.remove(index);
}
_ => {}
}
}
attrs.remove(name);
}
pub fn remove_attributes(&self, ids: &[AttributeId]) {
for id in ids {
self.remove_attribute(*id);
}
}
pub fn linked_nodes(&self) -> LinkedNodes {
LinkedNodes::new(Ref::map(self.0.borrow(), |n| &n.linked_nodes))
}
pub fn is_used(&self) -> bool {
let self_borrow = self.0.borrow();
!self_borrow.linked_nodes.is_empty()
}
pub fn uses_count(&self) -> usize {
let self_borrow = self.0.borrow();
self_borrow.linked_nodes.len()
}
}
fn same_rc<T>(a: &Rc<T>, b: &Rc<T>) -> bool {
let a: *const T = &**a;
let b: *const T = &**b;
a == b
}
impl Clone for Node {
fn clone(&self) -> Node {
Node(self.0.clone())
}
}
impl PartialEq for Node {
fn eq(&self, other: &Node) -> bool {
same_rc(&self.0, &other.0)
}
}
impl fmt::Debug for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.node_type() {
NodeType::Root => write!(f, "Root node"),
NodeType::Element => write!(f, "<{:?} id={:?}>", self.tag_name().unwrap(), self.id()),
NodeType::Declaration => write!(f, "<?{}?>", *self.text()),
NodeType::Comment => write!(f, "<!--{}-->", *self.text()),
NodeType::Cdata => write!(f, "<![CDATA[{}]]>", *self.text()),
NodeType::Text => write!(f, "{}", *self.text()),
}
}
}