use std::cell::{
RefCell,
Ref,
RefMut
};
use std::rc::Rc;
use std::fmt;
use {
Attribute,
AttributeId,
AttributeNameRef,
Attributes,
AttributeValue,
Children,
Descendants,
Document,
ElementId,
Error,
LinkedNodes,
Name,
NameRef,
NodeType,
Parents,
SvgId,
TagName,
TagNameRef,
Traverse,
};
use super::node_data::NodeData;
macro_rules! try_opt {
($expr: expr) => {
match $expr {
Some(value) => value,
None => return None
}
}
}
impl SvgId for ElementId {
fn name(&self) -> &str { self.name() }
}
impl<'a, N, V> From<(N, V)> for Attribute
where AttributeNameRef<'a>: From<N>, AttributeValue: From<V>
{
fn from(v: (N, V)) -> Self {
Attribute::new(v.0, v.1)
}
}
impl<'a> From<(AttributeId, Node)> for Attribute {
fn from(v: (AttributeId, Node)) -> Self {
if v.0 == AttributeId::XlinkHref {
Attribute::new(v.0, AttributeValue::Link(v.1))
} else {
Attribute::new(v.0, AttributeValue::FuncLink(v.1))
}
}
}
pub struct Node(pub Rc<RefCell<NodeData>>);
impl Node {
pub fn document(&self) -> Document {
debug_assert_ne!(self.node_type(), NodeType::Root);
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 parents_with_self(&self) -> Parents {
Parents::new(Some(self.clone()))
}
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(Rc::clone(try_opt!(self.0.borrow().first_child.as_ref()))))
}
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().prev_sibling.as_ref()).upgrade())))
}
pub fn next_sibling(&self) -> Option<Node> {
Some(Node(Rc::clone(try_opt!(self.0.borrow().next_sibling.as_ref()))))
}
pub fn descendants(&self) -> Descendants {
Descendants::new(self)
}
pub fn traverse(&self) -> Traverse {
Traverse::new(self)
}
pub fn detach(&mut self) {
self.0.borrow_mut().detach();
}
pub fn remove(&mut self) {
Node::_remove(self);
self.detach();
}
fn _remove(node: &mut 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 mut 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 mut child in node.children().svg() {
Node::_remove(&mut child);
}
}
pub fn drain<P>(&mut self, f: P) -> usize
where P: Fn(&Node) -> bool
{
let mut count = 0;
Node::_drain(self, &f, &mut count);
count
}
fn _drain<P>(parent: &mut Node, f: &P, count: &mut usize)
where P: Fn(&Node) -> bool
{
let mut node = parent.first_child();
while let Some(mut n) = node {
if f(&n) {
node = n.next_sibling();
n.remove();
*count += 1;
} else {
if n.has_children() {
Node::_drain(&mut n, f, count);
}
node = n.next_sibling();
}
}
}
pub fn make_copy(&self) -> Node {
match self.node_type() {
NodeType::Element => {
let mut elem = self.document().create_element(self.tag_name().unwrap().into_ref());
for attr in self.attributes().iter() {
elem.set_attribute(attr.clone());
}
elem
}
_ => {
self.document().create_node(self.node_type(), &*self.text())
}
}
}
pub fn make_deep_copy(&self) -> Node {
let mut root = self.make_copy();
Node::_make_deep_copy(&mut root, self);
root
}
fn _make_deep_copy(parent: &mut Node, node: &Node) {
for child in node.children() {
let mut new_node = child.make_copy();
parent.append(&new_node);
if child.has_children() {
Node::_make_deep_copy(&mut new_node, &child);
}
}
}
pub fn append(&mut self, new_child: &Node) {
let mut this = self.0.borrow_mut();
let mut last = None;
let nc = new_child.clone();
{
let mut child = nc.0.borrow_mut();
child.detach();
child.parent = Some(Rc::downgrade(&self.0));
if let Some(last_weak) = this.last_child.take() {
if let Some(last_strong) = last_weak.upgrade() {
child.prev_sibling = Some(last_weak);
last = Some(last_strong);
}
}
this.last_child = Some(Rc::downgrade(&nc.0));
}
if let Some(last) = last {
let mut last = last.borrow_mut();
debug_assert!(last.next_sibling.is_none());
last.next_sibling = Some(nc.0);
} else {
debug_assert!(this.first_child.is_none());
this.first_child = Some(nc.0);
}
}
pub fn prepend(&mut self, new_child: &Node) {
let mut this = self.0.borrow_mut();
{
let mut child = new_child.0.borrow_mut();
child.detach();
child.parent = Some(Rc::downgrade(&self.0));
match this.first_child.take() {
Some(first) => {
{
let mut first = first.borrow_mut();
debug_assert!(first.prev_sibling.is_none());
first.prev_sibling = Some(Rc::downgrade(&new_child.0));
}
child.next_sibling = Some(first);
}
None => {
debug_assert!(this.first_child.is_none());
this.last_child = Some(Rc::downgrade(&new_child.0));
}
}
}
this.first_child = Some(new_child.clone().0);
}
pub fn insert_after(&mut self, new_sibling: &Node) {
let mut this = self.0.borrow_mut();
{
let mut child = new_sibling.0.borrow_mut();
child.detach();
child.parent = this.parent.clone();
child.prev_sibling = Some(Rc::downgrade(&self.0));
match this.next_sibling.take() {
Some(next) => {
{
let mut next = next.borrow_mut();
debug_assert!({
let weak = next.prev_sibling.as_ref().unwrap();
same_rc(&weak.upgrade().unwrap(), &self.0)
});
next.prev_sibling = Some(Rc::downgrade(&new_sibling.0));
}
child.next_sibling = Some(next);
}
None => {
Node::update_parent(&this, |mut p| {
p.last_child = Some(Rc::downgrade(&new_sibling.0))
});
}
}
}
this.next_sibling = Some(new_sibling.clone().0);
}
pub fn insert_before(&mut self, new_sibling: &Node) {
let mut this = self.0.borrow_mut();
let mut prev_opt = None;
{
let mut child = new_sibling.0.borrow_mut();
child.detach();
child.parent = this.parent.clone();
child.next_sibling = Some(Rc::clone(&self.0));
if let Some(prev_weak) = this.prev_sibling.take() {
if let Some(prev_strong) = prev_weak.upgrade() {
child.prev_sibling = Some(prev_weak);
prev_opt = Some(prev_strong);
}
}
this.prev_sibling = Some(Rc::downgrade(&new_sibling.0));
}
if let Some(prev) = prev_opt {
let mut prev = prev.borrow_mut();
debug_assert!({
let rc = prev.next_sibling.as_ref().unwrap();
same_rc(rc, &self.0)
});
prev.next_sibling = Some(new_sibling.clone().0);
} else {
Node::update_parent(&this, |mut p| {
p.first_child = Some(new_sibling.clone().0)
});
}
}
fn update_parent<F>(this: &RefMut<NodeData>, mut f: F)
where F: FnMut(RefMut<NodeData>)
{
if let Some(parent) = this.parent.as_ref() {
if let Some(parent) = parent.upgrade() {
f(parent.borrow_mut());
}
}
}
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(&mut self) -> RefMut<String> {
RefMut::map(self.0.borrow_mut(), |n| &mut n.text)
}
pub fn set_text(&mut 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 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 set_id<S: Into<String>>(&mut 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 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 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_tag_name<'a, T>(&mut 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 attributes(&self) -> Ref<Attributes> {
Ref::map(self.0.borrow(), |n| &n.attributes)
}
pub fn attributes_mut(&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 {
if let Some(attr) = self.attributes().get(id) { attr.visible } else { false }
}
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 set_attribute<T>(&mut self, v: T)
where T: Into<Attribute>
{
self.set_attribute_checked(v).unwrap();
}
pub fn set_attribute_checked<T>(&mut self, v: T) -> Result<(), Error>
where T: Into<Attribute>
{
debug_assert_eq!(self.node_type(), NodeType::Element);
let attr: Attribute = v.into();
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())?;
return Ok(());
}
_ => {}
}
}
self.set_simple_attribute(attr);
Ok(())
}
fn set_simple_attribute(&mut self, attr: Attribute) {
debug_assert!(!attr.is_link() && !attr.is_func_link());
self.remove_attribute(attr.name.into_ref());
let mut attrs = self.attributes_mut();
attrs.insert(attr);
}
fn set_link_attribute(&mut self, id: AttributeId, node: Node) -> Result<(), Error> {
if node.id().is_empty() {
return Err(Error::ElementMustHaveAnId);
}
if *self.id() == *node.id() {
return Err(Error::ElementCrosslink);
}
if self.linked_nodes().any(|n| n == 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_impl(a);
}
{
let mut value_borrow = node.0.borrow_mut();
value_borrow.linked_nodes.push(Rc::downgrade(&self.0));
}
Ok(())
}
pub fn remove_attribute<'a, N>(&mut self, name: N)
where AttributeNameRef<'a>: From<N>, N: Copy
{
if !self.has_attribute(name) {
return;
}
if let Some(value) = self.attributes().get_value(name) {
match *value {
AttributeValue::Link(ref node) | AttributeValue::FuncLink(ref node) => {
let self_borrow = &self.0;
let mut node_borrow = node.0.borrow_mut();
let ln = &mut node_borrow.linked_nodes;
let index = ln.iter().position(|x| {
same_rc(&x.upgrade().unwrap(), self_borrow)
}).unwrap();
ln.remove(index);
}
_ => {}
}
}
self.attributes_mut().remove_impl(name);
}
pub fn remove_attributes(&mut 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()
}
}
impl Clone for Node {
fn clone(&self) -> Node {
Node(Rc::clone(&self.0))
}
}
impl PartialEq for Node {
fn eq(&self, other: &Node) -> bool {
same_rc(&self.0, &other.0)
}
}
fn same_rc<T>(a: &Rc<T>, b: &Rc<T>) -> bool {
let a: *const T = &**a;
let b: *const T = &**b;
a == b
}
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()),
}
}
}