TEST(TestMeiDocument, FlattenedDocTree) { Mei *mei = new Mei(); Music *mus = new Music(); Body *body = new Body(); Staff *staff = new Staff(); Staff *s2 = new Staff(); Note *n1 = new Note(); Note *n2 = new Note(); Note *n3 = new Note(); MeiDocument *doc = new MeiDocument(); mei->addChild(mus); // empty since mei not added as document root yet ASSERT_TRUE(doc->getFlattenedTree().empty()); doc->setRootElement(mei); ASSERT_EQ(2, doc->getFlattenedTree().size()); mus->addChild(body); body->addChild(staff); body->addChild(s2); staff->addChild(n1); staff->addChild(n2); s2->addChild(n3); doc->lookBack(n2, "mei"); ASSERT_EQ(8, doc->getFlattenedTree().size()); staff->removeChild(n2); ASSERT_EQ(7, doc->getFlattenedTree().size()); ASSERT_EQ(s2, doc->getFlattenedTree()[5]); staff->removeChildrenWithName("note"); ASSERT_EQ(6, doc->getFlattenedTree().size()); body->deleteAllChildren(); ASSERT_EQ(3, doc->getFlattenedTree().size()); std::vector<MeiElement*> newChildren; Staff *newStaff1 = new Staff(); Staff *newStaff2 = new Staff(); newChildren.push_back(newStaff1); newChildren.push_back(newStaff2); body->setChildren(newChildren); ASSERT_EQ(5, doc->getFlattenedTree().size()); // check contents MeiElement* elements[] = { mei, mus, body, newStaff1, newStaff2 }; std::vector<MeiElement*> rightOrder (elements, elements + sizeof(elements) / sizeof(MeiElement)); for (int i = 0; i < rightOrder.size(); i++) { // check don't overshoot memory allocation ASSERT_LT(i, doc->getFlattenedTree().size()); ASSERT_EQ(rightOrder[i], doc->getFlattenedTree()[i]); } }
// after adding a root to a document, you can find an element TEST(TestMeiDocument, ElementById) { Mei *mei = new Mei(); Music *mus = new Music(); Body *body = new Body(); Staff *staff = new Staff(); Staff *s2 = new Staff(); Note *n1 = new Note(); string wantedId = n1->getId(); Note *n2 = new Note(); Note *n3 = new Note(); Note *n4 = new Note(); MeiDocument *doc = new MeiDocument(); ASSERT_EQ(NULL, doc->getElementById(wantedId)); mei->addChild(mus); mus->addChild(body); body->addChild(staff); body->addChild(s2); staff->addChild(n1); staff->addChild(n2); staff->addChild(n3); s2->addChild(n4); doc->setRootElement(mei); ASSERT_EQ(n1, doc->getElementById(wantedId)); ASSERT_EQ(NULL, doc->getElementById("some-unknown-id")); // After adding the root element, making a new element works Note *n5 = new Note(); string newid = n5->getId(); s2->addChild(n5); ASSERT_EQ(n5, doc->getElementById(newid)); // removing the element from the document, clear from document map s2->removeChild(n5); ASSERT_EQ(NULL, doc->getElementById(newid)); }
TEST(TestMeiDocument, ElementsByName) { Mei *mei = new Mei(); Music *mus = new Music(); Body *body = new Body(); Staff *staff = new Staff(); Staff *s2 = new Staff(); Note *n1 = new Note(); string wantedId = n1->getId(); Note *n2 = new Note(); Note *n3 = new Note(); Note *n4 = new Note(); mei->addChild(mus); mus->addChild(body); body->addChild(staff); body->addChild(s2); staff->addChild(n1); staff->addChild(n2); staff->addChild(n3); s2->addChild(n4); MeiDocument *doc = new MeiDocument(); doc->setRootElement(mei); std::vector<MeiElement*> notes = doc->getElementsByName("note"); ASSERT_EQ(4, notes.size()); std::vector<MeiElement*> rests = doc->getElementsByName("rest"); ASSERT_EQ(0, rests.size()); // After adding the root element, making a new element works Note *n5 = new Note(); staff->addChild(n5); std::vector<MeiElement*> notes_new = doc->getElementsByName("note"); ASSERT_EQ(5, notes_new.size()); }
TEST(TestMeiDocument, DocumentPointers) { Mei *mei = new Mei(); Music *mus = new Music(); Body *body = new Body(); Staff *staff = new Staff(); // If an element is added as a child and neither element is attached to a document, nothing happens. ASSERT_EQ(NULL, mei->getDocument()); mei->addChild(mus); ASSERT_EQ(NULL, mus->getDocument()); MeiDocument *doc = new MeiDocument(); // add root to document, all elements should have their document pointer updated mus->addChild(body); doc->setRootElement(mei); ASSERT_EQ(doc, mei->getDocument()); ASSERT_EQ(doc, mus->getDocument()); ASSERT_EQ(doc, body->getDocument()); // add another element as a child, child element should be linked to the same document body->addChild(staff); ASSERT_EQ(doc, staff->getDocument()); }
void CScribeToNeoScribeXML::SegmentScribe2MEIXML(const CScribeReaderVisitable& scribe_data) { std::unordered_set<std::string> rep_no_record; for (std::vector<scribe_part>::const_iterator part = scribe_data.GetScribeParts().begin(); part != scribe_data.GetScribeParts().end(); part++) { int i = 0; //save record of first part scribe_part first_part = *part; //create an instance of XML doc representation, etc. delete doc; doc = new MeiDocument(); Mei *mei = new Mei; doc->setRootElement(mei); /* MEI - <meiHead> - FileDescription - EncodingDescription - Work Description - Revision Description */ //create MEIhead to contain file, encoding, work and revision description MeiHead* mei_head = new MeiHead; mei->addChild(mei_head); AltId* altId = new AltId; mei_head->addChild(altId); if (scribe_data.GetType()==scribe_type::trecento) { altId->addAttribute("type", "repnum"); altId->setValue(part->rep_num); } else if (scribe_data.GetType()==scribe_type::trecento) { altId->addAttribute("type", "cao"); altId->setValue(std::to_string(part->cao_num)); } //Create and link fileDesc FileDesc* fileDesc = Scribe2MEIFileDesc(); mei_head->addChild(fileDesc); //Create and link encodingDesc EncodingDesc* encodingDesc = Scribe2MEIEncoderDesc(); mei_head->addChild(encodingDesc); //Create and link workDesc WorkDesc* workDesc = Scribe2MEIWorkDesc(); mei_head->addChild(workDesc); //</meiHead> - not really at this stage - other elements completed in main routine //music - contains all music data Music* music = new Music; mei->addChild(music); Mdiv* mdiv = new Mdiv; //for chant source this needs to be specified repeatedly, with n and type attributes music->addChild(mdiv); Score* score = new Score; mdiv->addChild(score); //start adding score definitions - child of score ScoreDef* scoredef = new ScoreDef; score->addChild(scoredef); StaffGrp* staffgrp = new StaffGrp; scoredef->addChild(staffgrp); staffgrp->setId("all"); //skip along and collect parts - all have the same REPNUM std::string xml_file_name(""); if (scribe_data.GetType()==scribe_type::trecento) { do { ++i; if (i==1) { Scribe2MEIXMLFileData(fileDesc, *part); Scribe2MEIXMLWorkData(workDesc, *part); } //add section - child of score Section* section = new Section; score->addChild(section); //handle staff and link to section Staff* staff = Scribe2MEIXMLStaff(scribe_data, *part, staffgrp, i); section->addChild(staff); //or TiXmlElement* layer;? part++; } while ( part->rep_num==first_part.rep_num && part != scribe_data.GetScribeParts().end()); part--; // step back to last part in piece xml_file_name = first_part.rep_num; //find duplicates - doesn't find triplicates if (rep_no_record.find(part->rep_num) == rep_no_record.end()) { rep_no_record.insert(part->rep_num); } else { xml_file_name += " copy"; } } else if (scribe_data.GetType()==scribe_type::chant) { Scribe2MEIXMLFileData(fileDesc, *part); Scribe2MEIXMLWorkData(workDesc, *part); //add section - child of score Section* section = new Section; score->addChild(section); //handle staff and link to section Staff* staff = Scribe2MEIXMLStaff(scribe_data, *part, staffgrp, i); section->addChild(staff); xml_file_name = part->abbrev_ms + ZeroPadNumber(part->partID,4)+ " (" + std::to_string(first_part.cao_num) + ")"; } //need to check if there already exists a file with the same name xml_file_name += ".xml"; SaveMEIXML(xml_file_name); } }
MeiDocument* CScribeToNeoScribeXML::Scribe2MEIXML(const CScribeReaderVisitable& scribe_data) { Mei* mei = new Mei; doc->setRootElement(mei); //create MEIhead to contain file, encoding, work and revision description MeiHead* mei_head = new MeiHead; //"meiHead" mei->addChild(mei_head); //Create and link fileDesc FileDesc* fileDesc = Scribe2MEIFileDesc(); mei_head->addChild(fileDesc); //Create and link encodingDesc EncodingDesc* encodingDesc = Scribe2MEIEncoderDesc(); mei_head->addChild(encodingDesc); //Create and link workDesc WorkDesc* workDesc = Scribe2MEIWorkDesc(); mei_head->addChild(workDesc); //</meiHead> - not really at this stage - other elements completed in main routine //music - contains all music data Music* music = new Music; mei->addChild(music); Mdiv* mdiv = new Mdiv; //for chant source this needs to be specified repeatedly, with n and type attributes music->addChild(mdiv); Score* score = new Score; mdiv->addChild(score); //start adding score definitions - child of score ScoreDef* scoredef = new ScoreDef; score->addChild(scoredef); StaffGrp* staffgrp = new StaffGrp; scoredef->addChild(staffgrp); staffgrp->setId("all"); int i=0; for (std::vector<scribe_part>::const_iterator partit = scribe_data.GetScribeParts().begin(); partit!=scribe_data.GetScribeParts().end(); partit++) { ++i; if (i==1) { Scribe2MEIXMLFileData(fileDesc, *partit); Scribe2MEIXMLWorkData(workDesc, *partit); } //add section - child of score Section* section = new Section(); score->addChild(section); //handle staff and link to section Staff* staff = Scribe2MEIXMLStaff(scribe_data, *partit, staffgrp, i); section->addChild(staff); } return doc; }