use std::convert::TryFrom;
use std::rc::{Rc, Weak};
use std::collections::HashMap;
use crate::xdmerror::*;
use crate::qname::*;
use crate::output::OutputDefinition;
use crate::value::Value;
use crate::item::{NodeType, INode, MNode};
use crate::parsexml::content;
#[derive(Clone, Default, PartialEq)]
pub struct ADoc {
pub xmldecl: Option<XMLDecl>,
pub prologue: Vec<RANode>,
pub content: Vec<RANode>,
pub epilogue: Vec<RANode>,
}
impl ADoc {
fn new() -> Self {
ADoc{..Default::default()}
}
pub fn set_xmldecl(&mut self, x: XMLDecl) {
self.xmldecl = Some(x)
}
pub fn get_xmldecl(&self) -> &Option<XMLDecl> {
&self.xmldecl
}
fn push_content(&mut self, n: RANode) {
self.content.push(n)
}
fn to_xml(&self) -> String {
let mut result = String::new();
self.content.iter()
.for_each(|c| {
result.push_str(c.to_xml().as_str())
});
result
}
}
pub struct ADocBuilder(ADoc);
impl ADocBuilder {
pub fn new() -> Self {
ADocBuilder(ADoc::new())
}
pub fn xmldecl(mut self, x: XMLDecl) -> Self {
self.0.xmldecl = Some(x);
self
}
pub fn prologue(mut self, p: Vec<Rc<ANode>>) -> Self {
self.0.prologue = p;
self
}
pub fn content(mut self, p: Vec<Rc<ANode>>) -> Self {
self.0.content = p;
self
}
pub fn epilogue(mut self, p: Vec<Rc<ANode>>) -> Self {
self.0.epilogue = p;
self
}
pub fn build(self) -> ADoc {
self.0
}
}
#[derive(Clone, Default, PartialEq)]
pub struct ANode {
node_type: NodeType,
children: Vec<RANode>,
attributes: HashMap<QualifiedName, Rc<ANode>>,
name: Option<QualifiedName>,
value: Option<Value>,
pi_name: Option<String>,
dtd: Option<DTDDecl>,
reference: Option<QualifiedName>,
}
impl ANode {
fn new(n: NodeType) -> Self {
ANode{
node_type: n,
children: vec![],
attributes: HashMap::new(),
name: None,
value: None,
pi_name: None,
dtd: None,
reference: None,
}
}
pub fn name(&self) -> Option<QualifiedName> {
self.name.clone()
}
pub fn value(&self) -> Option<Value> {
self.value.clone()
}
pub fn pi_name(&self) -> Option<String> {
self.pi_name.clone()
}
pub fn reference(&self) -> Option<QualifiedName> {
self.reference.clone()
}
}
pub struct ANodeBuilder(ANode);
impl ANodeBuilder {
pub fn new(n: NodeType) -> Self {
ANodeBuilder(ANode::new(n))
}
pub fn name(mut self, qn: QualifiedName) -> Self {
self.0.name = Some(qn);
self
}
pub fn value(mut self, v: Value) -> Self {
self.0.value = Some(v);
self
}
pub fn pi_name(mut self, pi: String) -> Self {
self.0.pi_name = Some(pi);
self
}
pub fn dtd(mut self, d: DTDDecl) -> Self {
self.0.dtd = Some(d);
self
}
pub fn reference(mut self, qn: QualifiedName) -> Self {
self.0.reference = Some(qn);
self
}
pub fn build(self) -> ANode {
self.0
}
}
pub type RANode = Rc<ANode>;
impl MNode for RANode {
type NodeIterator = Box<dyn Iterator<Item = RANode>>;
type Immutable = RBNode;
fn new_element(&self, qn: QualifiedName) -> Result<Self, Error> {
Ok(Rc::new(
ANodeBuilder::new(NodeType::Element)
.name(qn)
.build()
))
}
fn new_text(&self, v: Value) -> Result<Self, Error> {
Ok(Rc::new(
ANodeBuilder::new(NodeType::Text)
.value(v)
.build()
))
}
fn new_attribute(&self, qn: QualifiedName, v: Value) -> Result<Self, Error> {
Ok(Rc::new(
ANodeBuilder::new(NodeType::Attribute)
.name(qn)
.value(v)
.build()
))
}
fn node_type(&self) -> NodeType {
self.node_type.clone()
}
fn name(&self) -> QualifiedName {
self.name.as_ref().map_or(
QualifiedName::new(None, None, String::new()),
|n| n.clone()
)
}
fn value(&self) -> Value {
self.value.as_ref().map_or(
Value::from(""),
|v| v.clone(),
)
}
fn to_string(&self) -> String {
String::from("not yet implemented")
}
fn to_xml(&self) -> String {
match self.node_type {
NodeType::Document => {
self.children.iter()
.fold(
String::new(),
|mut result, c| {
result.push_str(c.to_xml().as_str());
result
}
)
}
NodeType::Element => {
let mut result = String::from("<");
result.push_str(self.name().as_ref().to_string().as_str());
result.push_str(">");
self.child_iter()
.for_each(|c| {
result.push_str(c.to_xml().as_str())
});
result.push_str("</");
result.push_str(self.name().as_ref().to_string().as_str());
result.push_str(">");
result
}
NodeType::Text => self.value().to_string(),
_ => String::new(), }
}
fn to_xml_with_options(&self, _od: &OutputDefinition) -> String {
String::from("TODO")
}
fn child_iter(&self) -> Self::NodeIterator {
Box::new(ANodeChildren::new(self))
}
fn push(&mut self, n: Rc<ANode>) -> Result<(), Error> {
match Rc::get_mut(self) {
Some(p) => {
p.children.push(n);
Ok(())
}
None => Result::Err(Error::new(ErrorKind::Unknown, String::from("unable to mutate node")))
}
}
fn add_attribute(&mut self, _att: Rc<ANode>) -> Result<(), Error> {
Result::Err(Error::new(ErrorKind::NotImplemented, String::from("not implemented")))
}
}
pub struct ANodeChildren {
v: Vec<Rc<ANode>>,
i: usize,
}
impl ANodeChildren {
fn new(n: &Rc<ANode>) -> Self {
match n.node_type() {
NodeType::Element => {
ANodeChildren{v: n.children.clone(), i: 0}
}
_ => {
ANodeChildren{v: vec![], i: 0}
}
}
}
}
impl Iterator for ANodeChildren {
type Item = RANode;
fn next(&mut self) -> Option<RANode> {
match self.v.get(self.i) {
Some(c) => {
self.i += 1;
Some(c.clone())
}
None => None,
}
}
}
#[derive(Clone, PartialEq)]
pub struct XMLDecl {
version: String,
encoding: Option<String>,
standalone: Option<String>
}
impl XMLDecl {
pub fn new(version: String, encoding: Option<String>, standalone: Option<String>) -> Self {
XMLDecl{version, encoding, standalone}
}
pub fn version(&self) -> String {
self.version.clone()
}
pub fn set_encoding(&mut self, e: String) {
self.encoding = Some(e)
}
pub fn encoding(&self) -> String {
self.encoding.as_ref().map_or(String::new(), |e| e.clone())
}
pub fn set_standalone(&mut self, s: String) {
self.standalone = Some(s)
}
pub fn standalone(&self) -> String {
self.standalone.as_ref().map_or(String::new(), |e| e.clone())
}
pub fn to_string(&self) -> String {
let mut result = String::from("<?xml version=\"");
result.push_str(self.version.as_str());
result.push('"');
self.encoding.as_ref().map(|e| {
result.push_str(" encoding=\"");
result.push_str(e.as_str());
result.push('"');
});
self.standalone.as_ref().map(|e| {
result.push_str(" standalone=\"");
result.push_str(e.as_str());
result.push('"');
});
result
}
}
pub struct XMLDeclBuilder(XMLDecl);
impl XMLDeclBuilder {
pub fn new() -> Self {
XMLDeclBuilder(XMLDecl{version: String::new(), encoding: None, standalone: None})
}
pub fn version(mut self, v: String) -> Self {
self.0.version = v;
self
}
pub fn encoding(mut self, v: String) -> Self {
self.0.encoding = Some(v);
self
}
pub fn standalone(mut self, v: String) -> Self {
self.0.standalone = Some(v);
self
}
pub fn build(self) -> XMLDecl {
self.0
}
}
#[derive(Clone, PartialEq)]
pub enum DTDDecl {
GeneralEntity(QualifiedName, String),
}
pub type RBNode = Rc<BNode>;
impl TryFrom<ADoc> for RBNode {
type Error = Error;
fn try_from(a: ADoc) -> Result<Self, Self::Error> {
let mut ent: HashMap<QualifiedName, Vec<Rc<ANode>>> = HashMap::new();
for p in &a.prologue {
if p.node_type() == NodeType::Unknown {
let DTDDecl::GeneralEntity(n, c) = p.dtd.as_ref().unwrap();
let (rest, e) = content(c.as_str()).map_err(|e| Error::new(ErrorKind::Unknown, e.to_string()))?;
if rest.len() != 0 {
return Result::Err(Error::new(ErrorKind::Unknown, format!("unable to parse general entity \"{}\"", n.to_string())))
}
match ent.insert(n.clone(), e) {
Some(_) => {
return Result::Err(Error::new(ErrorKind::Unknown, format!("general entity \"{}\" already defined", n.to_string())))
}
None => {}
}
}
}
Ok(Rc::new_cyclic(|weak_self| {
let mut new: Vec<RBNode> = vec![];
let mut prologue = a.prologue.into_iter()
.map(|n| {
BNode::from_anode(n, Some(weak_self.clone()), &ent)
})
.collect();
new.append(&mut prologue);
let mut content = a.content.into_iter()
.map(|n| {
BNode::from_anode(n, Some(weak_self.clone()), &ent)
})
.collect();
new.append(&mut content);
let mut epilogue = a.epilogue.into_iter()
.map(|n| {
BNode::from_anode(n, Some(weak_self.clone()), &ent)
})
.collect();
new.append(&mut epilogue);
BNode{
node_type: NodeType::Document,
parent: None,
children: new,
name: None, value: None,
}
}))
}
}
pub struct BNode {
node_type: NodeType,
parent: Option<Weak<BNode>>,
children: Vec<Rc<BNode>>,
name: Option<QualifiedName>,
value: Option<Value>,
}
impl BNode {
fn from_anode(
n: Rc<ANode>,
parent: Option<Weak<BNode>>,
entities: &HashMap<QualifiedName, Vec<Rc<ANode>>>
) -> Rc<Self> {
Rc::new_cyclic(|weak_self| {
match n.node_type() {
NodeType::Element => {
let children: Vec<_> = n.child_iter()
.map(|child| {
BNode::from_anode(child, Some(weak_self.clone()), entities)
})
.collect();
BNode{
node_type: NodeType::Element,
parent, children,
name: Some(n.name()), value: None
}
}
NodeType::Attribute => {
BNode{
node_type: NodeType::Attribute,
parent, children: vec![],
name: Some(n.name()),
value: Some(n.value())
}
}
NodeType::Text => {
BNode{
node_type: NodeType::Text,
parent, children: vec![],
name: None,
value: Some(n.value())
}
}
NodeType::ProcessingInstruction => {
BNode{
node_type: NodeType::ProcessingInstruction,
parent, children: vec![],
name: Some(QualifiedName::new(None, None, n.pi_name().unwrap())),
value: Some(n.value())
}
}
NodeType::Comment => {
BNode{
node_type: NodeType::Comment,
parent, children: vec![],
name: None, value: Some(n.value())
}
}
_ => {
BNode{
node_type: NodeType::Unknown,
parent, children: vec![],
name: None, value: None
}
}
}
})
}
}
impl INode for RBNode {
type NodeIterator = Box<dyn Iterator<Item = RBNode>>;
type Mutable = RANode;
fn node_type(&self) -> NodeType {
self.node_type.clone()
}
fn name(&self) -> QualifiedName {
self.name.as_ref().map_or(
QualifiedName::new(None, None, String::new()),
|n| n.clone()
)
}
fn value(&self) -> Value {
self.value.as_ref().map_or(
Value::from(""),
|n| n.clone()
)
}
fn to_mnode(&self) -> Self::Mutable {
Rc::new(ANode{
node_type: self.node_type().clone(),
name: Some(self.name()),
value: Some(self.value()),
children: vec![],
attributes: HashMap::new(), pi_name: None,
dtd: None,
reference: None,
})
}
fn to_string(&self) -> String {
let mut result = String::new();
match self.node_type {
NodeType::Document |
NodeType::Element => {
self.descend_iter()
.filter(|n| n.node_type() == NodeType::Text)
.for_each(|n| result.push_str(n.value().to_string().as_str()))
}
_ => {
result.push_str(self.value().to_string().as_str())
}
}
result
}
fn to_xml(&self) -> String {
let mut result = String::new();
match self.node_type {
NodeType::Document => {
self.children.iter()
.for_each(|c| result.push_str(c.to_xml().as_str()));
}
NodeType::Element => {
let name = self.name.as_ref().unwrap();
result.push_str("<");
result.push_str(name.to_string().as_str());
result.push_str(">");
self.children.iter()
.for_each(|c| result.push_str(c.to_xml().as_str()));
result.push_str("</");
result.push_str(name.to_string().as_str());
result.push_str(">");
}
NodeType::Text => {
result.push_str(self.value.as_ref().unwrap().to_string().as_str())
}
_ => {}
}
result
}
fn to_xml_with_options(&self, _od: &OutputDefinition) -> String {
String::from("not yet implemented")
}
fn to_json(&self) -> String {
String::from("not yet implemented")
}
fn child_iter(&self) -> Self::NodeIterator {
Box::new(Children::new(self.clone()))
}
fn ancestor_iter(&self) -> Self::NodeIterator {
Box::new(Ancestors::new(self.clone()))
}
fn descend_iter(&self) -> Self::NodeIterator {
Box::new(Descendants::new(self.clone()))
}
fn next_iter(&self) -> Self::NodeIterator {
Box::new(Siblings::new(self.clone(), 1))
}
fn prev_iter(&self) -> Self::NodeIterator {
Box::new(Siblings::new(self.clone(), -1))
}
fn attribute_iter(&self) -> Self::NodeIterator {
Box::new(Attributes::new(self.clone()))
}
}
pub struct Children {
v: Vec<RBNode>,
i: usize,
}
impl Children {
fn new(n: RBNode) -> Self {
Children{v: n.children.clone(), i: 0}
}
}
impl Iterator for Children {
type Item = RBNode;
fn next(&mut self) -> Option<RBNode> {
match self.v.get(self.i) {
Some(c) => {
self.i += 1;
Some(c.clone())
}
None => None,
}
}
}
pub struct Ancestors {
cur: RBNode,
}
impl Ancestors {
fn new(n: RBNode) -> Self {
Ancestors{cur: n.clone()}
}
}
impl Iterator for Ancestors {
type Item = RBNode;
fn next(&mut self) -> Option<RBNode> {
let p = self.cur.parent.as_ref();
match p {
None => None,
Some(q) => {
match Weak::upgrade(q) {
None => None,
Some(r) => {
self.cur = r.clone();
Some(r)
}
}
}
}
}
}
pub struct Descendants{
v: Vec<RBNode>,
cur: usize,
}
impl Descendants {
fn new(n: RBNode) -> Self {
Descendants{
v: n.children.iter()
.fold(
vec![],
|mut acc, c| {
let mut d = descendant_add(c);
acc.append(&mut d);
acc
}
),
cur: 0,
}
}
}
fn descendant_add(n: &RBNode) -> Vec<RBNode> {
let mut result = vec![n.clone()];
n.children.iter()
.for_each(|c| {
let mut l = descendant_add(c);
result.append(&mut l);
});
result
}
impl Iterator for Descendants {
type Item = RBNode;
fn next(&mut self) -> Option<RBNode> {
match self.v.get(self.cur) {
Some(n) => {
self.cur += 1;
Some(n.clone())
}
None => None,
}
}
}
pub struct Siblings(RBNode);
impl Siblings {
fn new(n: RBNode, _dir: i32) -> Self {
Siblings(n.clone())
}
}
impl Iterator for Siblings {
type Item = RBNode;
fn next(&mut self) -> Option<RBNode> {
None
}
}
pub struct Attributes(RBNode);
impl Attributes {
fn new(n: RBNode) -> Self {
Attributes(n.clone())
}
}
impl Iterator for Attributes {
type Item = RBNode;
fn next(&mut self) -> Option<RBNode> {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_a() {
let ad = ADocBuilder::new()
.content(vec![
Rc::new(
ANodeBuilder::new(NodeType::Element)
.name(QualifiedName::new(None, None, String::from("Test")))
.build()
)
])
.build();
assert_eq!(ad.to_xml(), "<Test></Test>")
}
#[test]
fn b_from_a() {
let ad = ADocBuilder::new()
.content(vec![
Rc::new(
ANodeBuilder::new(NodeType::Element)
.name(QualifiedName::new(None, None, String::from("Test")))
.build()
)
])
.build();
let bd = RBNode::try_from(ad).expect("unable to convert ADoc to BNode document");
assert_eq!(bd.to_xml(), "<Test></Test>")
}
#[test]
fn b_descend() {
let mut an1 = Rc::new(
ANodeBuilder::new(NodeType::Element)
.name(QualifiedName::new(None, None, String::from("Test")))
.build()
);
an1.push(Rc::new(
ANodeBuilder::new(NodeType::Text)
.value(Value::from("one-1"))
.build()
))
.expect("unable to add node");
let mut an2 = Rc::new(
ANodeBuilder::new(NodeType::Element)
.name(QualifiedName::new(None, None, String::from("Level1")))
.build()
);
let an3 = Rc::new(
ANodeBuilder::new(NodeType::Text)
.value(Value::from("two"))
.build()
);
an2.push(an3)
.expect("unable to add node");
an1.push(an2)
.expect("unable to add node");
let an4 = Rc::new(
ANodeBuilder::new(NodeType::Text)
.value(Value::from("one-2"))
.build()
);
an1.push(an4)
.expect("unable to add node");
let ad = ADocBuilder::new()
.content(vec![an1])
.build();
let bd = RBNode::try_from(ad).expect("unable to convert ADoc to BNode document");
let dit = bd.descend_iter();
assert_eq!(dit.count(), 5)
}
}