source: trunk/src/core/RpLibrary.cc @ 489

Last change on this file since 489 was 476, checked in by nkissebe, 18 years ago

std::string *list[listLen] is not allowed by ISO C++ and enforced by Microsoft C++ (2005). Rewrote to dynamically allocate.

File size: 43.6 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture Library Source
4 *
5 * ======================================================================
6 *  AUTHOR:  Derrick Kearney, Purdue University
7 *  Copyright (c) 2004-2005  Purdue Research Foundation
8 *
9 *  See the file "license.terms" for information on usage and
10 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * ======================================================================
12 */
13
14#include "RpLibrary.h"
15#include "RpEntityRef.h"
16
17static RpEntityRef ERTranslator;
18
19/**********************************************************************/
20// METHOD: _get_attribute()
21/// Return the attribute value matching the provided attribute name.
22/**
23 */
24
25std::string
26RpLibrary::_get_attribute(scew_element* element, std::string attributeName)
27{
28    scew_attribute* attribute = NULL;
29    std::string attrVal;
30    // int attrValSize = 0;
31
32    if (element != NULL)
33    {
34        if (scew_attribute_count(element) > 0) {
35
36            while((attribute=scew_attribute_next(element, attribute)) != NULL)
37            {
38                if (    strcmp( scew_attribute_name(attribute),
39                                attributeName.c_str()) == 0     ){
40                    attrVal = scew_attribute_value(attribute);
41                }
42            }
43        }
44        else {
45            // there are no attributes, count == 0
46        }
47    }
48
49    return attrVal;
50}
51
52/**********************************************************************/
53// METHOD: _path2list()
54/// Convert a path into a list of element names.
55/**
56 */
57
58int
59RpLibrary::_path2list (std::string& path, std::string** list, int listLen)
60{
61    std::string::size_type pos = 0;
62    std::string::size_type start = 0;
63    int index = 0;
64    int retVal = 0;
65
66    // listLen should be the highest index + 1
67    for (   pos = path.find(".",NO_CREATE_PATH);
68            (pos != std::string::npos) || (index >= listLen);
69            pos = path.find(".",pos)   )
70    {
71        list[index++] = new std::string(path.substr(start,pos-start));
72        start = ++pos;
73    }
74
75    // add the last path to the list
76    if (index < listLen) {
77        // error checking for path names?
78        // what if you get something like p1.p2. ?
79        list[index] = new std::string(path.substr(start,path.length()-start));
80    }
81
82    retVal = index++;
83
84    // null out the rest of the pointers so we know where to stop free'ing
85    while (index < listLen) {
86        list[index++] = NULL;
87    }
88
89    return retVal;
90}
91
92/**********************************************************************/
93// METHOD: _node2name()
94/// Retrieve the id of a node.
95/**
96 */
97
98std::string
99RpLibrary::_node2name (scew_element* node)
100{
101    // XML_Char const* name = _get_attribute(node,"id");
102    std::string name = _get_attribute(node,"id");
103    std::stringstream retVal;
104    XML_Char const* type = NULL;
105    scew_element* parent = NULL;
106    scew_element** siblings = NULL;
107    unsigned int count = 0;
108    int tmpCount = 0;
109    int index = 0;
110    std::string indexStr;
111
112    type = scew_element_name(node);
113    parent = scew_element_parent(node);
114
115    if (parent) {
116
117        // if (name == NULL) {
118        if (name.empty()) {
119            siblings = scew_element_list(parent, type, &count);
120            if (count > 0) {
121                tmpCount = count;
122                while ((index < tmpCount) && (siblings[index] != node)) {
123                    index++;
124                }
125
126                if (index < tmpCount) {
127
128                    if (index > 0) {
129
130                        retVal << type << --index;
131                    }
132                    else {
133
134                        retVal << type;
135                    }
136
137                    /*
138                    if (retVal == NULL) {
139                        // error with allocating space
140                        return NULL;
141                    }
142                    */
143                }
144            }
145
146            scew_element_list_free(siblings);
147
148        }
149        else {
150
151            retVal << name;
152        }
153    }
154
155    return (retVal.str());
156}
157
158/**********************************************************************/
159// METHOD: _node2comp()
160/// Retrieve the component name of a node
161/**
162 */
163
164std::string
165RpLibrary::_node2comp (scew_element* node)
166{
167    // XML_Char const* name = _get_attribute(node,"id");
168    std::string id = _get_attribute(node,"id");
169    std::stringstream retVal;
170    XML_Char const* type = NULL;
171    scew_element* parent = NULL;
172    scew_element** siblings = NULL;
173    unsigned int count = 0;
174    int tmpCount = 0;
175    int index = 0;
176    std::string indexStr;
177
178    type = scew_element_name(node);
179    parent = scew_element_parent(node);
180
181    if (parent) {
182        if (id.empty()) {
183            siblings = scew_element_list(parent, type, &count);
184            if (count > 0) {
185                tmpCount = count;
186                // figure out what the index value should be
187                while ((index < tmpCount) && (siblings[index] != node)) {
188                    index++;
189                }
190
191                if (index < tmpCount) {
192                    if (index > 0) {
193                        // retVal << type << --index;
194                        retVal << type << index;
195                    }
196                    else {
197                        retVal << type;
198                    }
199                }
200
201            }
202            else {
203                // count == 0 ??? this state should never be reached
204            }
205            scew_element_list_free(siblings);
206
207        }
208        else {
209            // node has attribute id
210            retVal << type << "(" << id << ")";
211
212        }
213    }
214
215    return (retVal.str());
216}
217
218/**********************************************************************/
219// METHOD: _node2path()
220/// Retrieve the full path name of a node
221/**
222 */
223
224std::string
225RpLibrary::_node2path (scew_element* node)
226{
227
228    std::stringstream path;
229    scew_element* snode = node;
230    scew_element* parent = NULL;
231
232    if (snode) {
233        parent = scew_element_parent(snode);
234        path.clear();
235
236        while (snode && parent) {
237
238            if (!path.str().empty()) {
239                path.str(_node2comp(snode) + "." + path.str());
240                // path.str("." + _node2comp(snode) + path.str());
241            }
242            else {
243                path.str(_node2comp(snode));
244                // path.str("." + _node2comp(snode));
245            }
246
247            snode = scew_element_parent(snode);
248            parent = scew_element_parent(snode);
249        }
250    }
251
252    return (path.str());
253}
254
255/**********************************************************************/
256// METHOD: _splitPath()
257/// Split a path (component) name into its tag name, index, and id
258/**
259 */
260
261int
262RpLibrary::_splitPath (std::string& path, std::string& tagName, int* idx, std::string& id )
263{
264    int stop = 0;
265    int start = 0;
266    int index = path.length();
267
268    if (index) {
269        index--;
270    }
271
272    if (!path.empty()) {
273        if (path[index] == ')') {
274            stop = index;
275            while (path[index] != '(') {
276                index--;
277            }
278            start = index+1;
279            // strncpy(id,path+start,stop-start);
280            // id = new std::string(path.substr(start,stop-start));
281            id = path.substr(start,stop-start);
282            index--;
283        }
284        if (isdigit(path[index])) {
285            stop = index;
286            while (isdigit(path[index])) {
287                index--;
288            }
289            // sscanf(path[index+1],"%d",idx);
290            sscanf(path.c_str()+index+1,"%d",idx);
291        }
292        if (isalpha(path[index])) {
293            start = 0;
294            stop = index+1;
295            // tagName = new std::string(path.substr(start,stop-start));
296            tagName = path.substr(start,stop-start);
297            // strncpy(tagName,path+start,stop-start);
298        }
299    }
300    else {
301        tagName = "";
302        *idx = 0;
303        id = "";
304    }
305
306    return 1;
307}
308
309/**********************************************************************/
310// METHOD: _find()
311/// Find or create a node and return it.
312/**
313 */
314
315scew_element*
316RpLibrary::_find(std::string path, int create)
317{
318    // std::string* tagName;
319    // std::string* id;
320    std::string tagName = "";
321    std::string id = "";
322    int index = 0;
323    int listLen = (path.length()/2)+1;
324    std::string** list;
325    int path_size = 0;
326    int listIdx = 0;
327    unsigned int count = 0;
328    int tmpCount = 0;
329    int lcv = 0;
330    std::string tmpId;
331
332    scew_element* tmpElement = this->root;
333    scew_element* node = NULL;
334    scew_element** eleList = NULL;
335
336
337    if (path.empty()) {
338        //user gave an empty path
339        // return this;
340        return tmpElement;
341    }
342
343    list = (std::string **) calloc(listLen, sizeof( std::string * ) );
344
345    if (!list) {
346        // error calloc'ing space for list
347        return NULL;
348    }
349
350    path_size = _path2list (path,list,listLen);
351
352    while ( (listIdx <= path_size) && (tmpElement != NULL ) ){
353
354        _splitPath(*(list[listIdx]),tagName,&index,id);
355
356        // if (id->empty()) {
357        if (id.empty()) {
358            /*
359            # If the name is like "type2", then look for elements with
360            # the type name and return the one with the given index.
361            # If the name is like "type", then assume the index is 0.
362            */
363
364            // eleList = scew_element_list(tmpElement, tagName->c_str(), &count);
365            eleList = scew_element_list(tmpElement, tagName.c_str(), &count);
366            tmpCount = count;
367            if (index < tmpCount) {
368                node = eleList[index];
369            }
370            else {
371                /* there is no element with the specified index */
372                node = NULL;
373            }
374
375            scew_element_list_free(eleList);
376            eleList = NULL;
377        }
378        else {
379
380            /* what if its like type2(id) ? */
381            /* still unresolved */
382
383            /*
384            # If the name is like "type(id)", then look for elements
385            # that match the type and see if one has the requested name.
386            # if the name is like "(id)", then look for any elements
387            # with the requested name.
388            */
389
390            // eleList = scew_element_list(tmpElement, tagName->c_str(), &count);
391            if (!tagName.empty()) {
392                eleList = scew_element_list(tmpElement, tagName.c_str(), &count);
393            }
394            else {
395                eleList = scew_element_list_all(tmpElement, &count);
396            }
397
398            tmpCount = count;
399            for (lcv = 0; (lcv < tmpCount); lcv++) {
400                tmpId = _get_attribute(eleList[lcv], "id");
401                if (!tmpId.empty()) {
402                    // if (*id == tmpId) {
403                    if (id == tmpId) {
404                        node = eleList[lcv];
405                        break;
406                    }
407                }
408            }
409
410            if (lcv >= tmpCount) {
411                node = NULL;
412            }
413
414            scew_element_list_free(eleList);
415            eleList = NULL;
416
417        }
418
419        if (node == NULL) {
420            if (create == NO_CREATE_PATH) {
421                // break out instead of returning because we still need to
422                // free the list variable
423                // return node;
424                tmpElement = node;
425                break;
426            }
427            else {
428                // create == CREATE_PATH
429                // we should create the rest of the path
430
431                // create the new element
432                // need to figure out how to properly number the new element
433                // node = scew_element_add(tmpElement,tagName->c_str());
434                node = scew_element_add(tmpElement,tagName.c_str());
435                if (! node) {
436                    // a new element was not created
437                }
438
439                // add an attribute and attrValue to the new element
440                // if (id && !id->empty()) {
441                    // scew_element_add_attr_pair(node,"id",id->c_str());
442                if (!id.empty()) {
443                    scew_element_add_attr_pair(node,"id",id.c_str());
444                }
445            }
446        }
447
448
449        // change this so youre not allocating and deallocating so much.
450        // make it static or something.
451        // if (tagName)    { delete (tagName); }
452        // if (id)         { delete (id); }
453        tagName = "";
454        id = "";
455        index = 0;
456        tmpElement = node;
457        listIdx++;
458    }
459
460    // need to free the strings inside of list
461
462    if (list) {
463        for (listIdx = 0; listIdx < listLen; listIdx++) {
464            if (list[listIdx]) {
465                delete(list[listIdx]);
466                list[listIdx] = NULL;
467            }
468        }
469
470        free(list);
471        list = NULL;
472    }
473
474
475    return tmpElement;
476}
477
478
479/**********************************************************************/
480// METHOD: element()
481/// Search the path of a xml tree and return a RpLibrary node.
482/**
483 * It is the user's responsibility to delete the object when
484 * they are finished using it?, else i need to make this static
485 */
486
487RpLibrary*
488RpLibrary::element (std::string path)
489{
490    RpLibrary* retLib = NULL;
491    scew_element* retNode = NULL;
492
493    if (!this->root) {
494        // library doesn't exist, do nothing;
495        return NULL;
496    }
497
498    /*
499    if (path.empty()) {
500        // an empty path returns the current RpLibrary
501        return this;
502    }
503    */
504
505    if (path.empty()) {
506        // this should be a smart pointer,
507        // if someone deletes the original this->root, this object is void
508        // and will be a memory leak.
509        // retNode = this->root;
510        retLib = new RpLibrary(*this);
511    }
512    else {
513        // get the node located at path
514        retNode = _find(path,NO_CREATE_PATH);
515
516        // if the node exists, create a rappture library object for it.
517        if (retNode) {
518            retLib = new RpLibrary( retNode,this->tree );
519        }
520    }
521
522    return retLib;
523}
524
525/**********************************************************************/
526// METHOD: entities()
527/// Search the path of a xml tree and return a list of its entities.
528/**
529 */
530
531std::list<std::string>
532RpLibrary::entities  (std::string path)
533{
534    std::list<std::string> queue;
535    std::list<std::string>::iterator iter;
536    std::list<std::string> retList;
537    std::list<std::string> childList;
538    std::list<std::string>::iterator childIter;
539
540    RpLibrary* ele = NULL;
541    std::string pathBack = "";
542
543    RpLibrary* child = NULL;
544    std::string childType = "";
545    std::string childPath = "";
546    std::string paramsPath = "";
547
548    RpLibrary* cchild = NULL;
549    std::string cchildType = "";
550    std::string cchildPath = "";
551
552    queue.push_back(path);
553    iter = queue.begin();
554
555    while( iter != queue.end() ) {
556        ele = this->element(*iter);
557        child = NULL;
558
559        if ((*iter).empty()) {
560            pathBack = "";
561        }
562        else {
563            pathBack = *iter + ".";
564        }
565
566        while ( ele && (child = ele->children("",child)) != NULL ) {
567            childList.push_back(child->nodeComp());
568            delete child;
569        }
570
571        childIter = childList.begin();
572
573        while (childIter != childList.end()) {
574            child = ele->element(*childIter);
575
576            childType = child->nodeType();
577            childPath = child->nodeComp();
578            if ( (childType == "group") || (childType == "phase") ) {
579                // add this path to the queue for paths to search
580                queue.push_back(pathBack+childPath);
581            }
582            else if (childType == "structure") {
583                // add this path to the return list
584                retList.push_back(pathBack+child->nodeComp());
585
586                // check to see if there is a ".current.parameters" node
587                // if so, add them to the queue list for paths to search
588                paramsPath = "current.parameters";
589                if (child->element(paramsPath) != NULL) {
590                    queue.push_back((pathBack+child->nodeComp()+"."+paramsPath));
591                }
592            }
593            else {
594                // add this path to the return list
595                retList.push_back(pathBack+child->nodeComp());
596
597                // look for embedded groups and phases
598                // add them to the queue list for paths to search
599                cchild = NULL;
600                while ( (cchild = child->children("",cchild)) != NULL ) {
601                    cchildType = cchild->nodeType();
602                    cchildPath = cchild->nodePath();
603                    if ( (cchildType == "group") || (cchildType == "phase") ) {
604                        // add this path to the queue for paths to search
605                        queue.push_back(cchildPath);
606                    }
607                    delete cchild;
608                }
609            }
610
611            childList.erase(childIter);
612            childIter = childList.begin();
613            delete child;
614        }
615
616        queue.erase(iter);
617        iter = queue.begin();
618    }
619
620    return retList;
621}
622
623/**********************************************************************/
624// METHOD: diff()
625/// find the differences between two xml trees.
626/**
627 */
628
629std::list<std::string>
630RpLibrary::diff (RpLibrary* otherLib, std::string path)
631{
632
633    std::list<std::string> thisVal; // two node list of specific entity's value
634    std::list<std::string> otherVal; // two node list of specific entity's value
635
636    std::list<std::string> thisv; // list of this library's entities
637    std::list<std::string>::iterator thisIter;
638
639    std::list<std::string> otherv; // list of other library's entities
640    std::list<std::string>::iterator otherIter;
641
642    std::list<std::string> retList;
643
644    std::string entry = "";
645    std::string thisSpath = "";  // temp string
646    std::string otherSpath = ""; // temp string
647
648    if ( (!this->root) || (!otherLib->root) ) {
649        // library doesn't exist, do nothing;
650        return retList;
651    }
652
653
654    thisv = this->entities(path);
655    otherv = otherLib->entities(path);
656
657    thisIter = thisv.begin();
658
659    while (thisIter != thisv.end() ) {
660        // reset otherIter for a new search.
661        otherIter = otherv.begin();
662        while ( (otherIter != otherv.end()) && (*otherIter != *thisIter) ) {
663            otherIter++;
664        }
665
666        //if (!path.empty()) {
667        //    thisSpath = path + "." + *thisIter;
668        //}
669        //else {
670        //    thisSpath = *thisIter;
671        //}
672        thisSpath = *thisIter;
673
674        if (otherIter == otherv.end()) {
675            // we've reached the end of the search
676            // and did not find anything, mark this as a '-'
677            thisVal = this->value(thisSpath);
678            retList.push_back("-");
679            retList.push_back(thisSpath);
680            retList.push_back(thisVal.front());
681            retList.push_back("");
682        }
683        else {
684
685            //if (!path.empty()) {
686            //    otherSpath = path + "." + *otherIter;
687            //}
688            //else {
689            //    otherSpath = *otherIter;
690            //}
691            otherSpath = *otherIter;
692
693            thisVal = this->value(thisSpath);
694            otherVal = otherLib->value(otherSpath);
695            if (thisVal.back() != otherVal.back()) {
696                // add the difference to the return list
697                retList.push_back("c");
698                retList.push_back(otherSpath);
699                retList.push_back(thisVal.front());
700                retList.push_back(otherVal.front());
701            }
702
703            // remove the last processed value from otherv
704            otherv.erase(otherIter);
705        }
706
707        // increment thisv's iterator.
708        thisIter++;
709    }
710
711    // add any left over values in otherv to the return list
712    otherIter = otherv.begin();
713    while ( otherIter != otherv.end() ) {
714
715        //if (!path.empty()) {
716        //    otherSpath = path + "." + *otherIter;
717        //}
718        //else {
719        //    otherSpath = *otherIter;
720        //}
721        otherSpath = *otherIter;
722
723        otherVal = otherLib->value(otherSpath);
724
725        retList.push_back("+");
726        retList.push_back(otherSpath);
727        retList.push_back("");
728        retList.push_back(otherVal.front());
729
730        otherv.erase(otherIter);
731        otherIter = otherv.begin();
732    }
733
734    return retList;
735}
736
737/**********************************************************************/
738// METHOD: value(path)
739/// Return a 2 element list containing the regular and normalized values.
740/**
741 */
742
743std::list<std::string>
744RpLibrary::value (std::string path)
745{
746    std::list<std::string> retArr;
747
748    std::string raw = "";
749    std::string val = "";
750
751    RpLibrary* ele = NULL;
752    RpLibrary* tele = NULL;
753
754    int childCount = 0;
755    std::stringstream valStr;
756
757    ele = this->element(path);
758
759    if (ele != NULL ) {
760
761        if (ele->nodeType() == "structure") {
762            raw = path;
763            // try to find a label to represent the structure
764            val = ele->get("about.label");
765
766            if (val == "") {
767               val = ele->get("current.about.label");
768            }
769
770            if (val == "") {
771               tele = ele->element("current");
772               if ( (tele != NULL) && (tele->nodeComp() != "") ) {
773                   tele->children("components",NULL,"",&childCount);
774                   valStr << "<structure> with " << childCount  << " components";
775                   val = valStr.str();
776               }
777            }
778
779        }
780        /*
781        else if (ele->nodeType() == "number") {
782            raw = "";
783            retArr[1] = "";
784            if ( (tele = ele->element("current")) != NULL) {
785                raw = tele->get();
786            }
787            else if ( (tele = ele->element("default")) != NULL) {
788                raw = tele->get();
789            }
790            val = raw
791            if ( "" != raw) {
792                // normalize the units
793                units = ele->get("units");
794                if ( "" != units) {
795
796                }
797        }
798        */
799        else {
800            raw = "";
801            if ( (tele = ele->element("current")) != NULL) {
802                raw = tele->get();
803            }
804            else if ( (tele = ele->element("default")) != NULL) {
805                raw = tele->get();
806            }
807            val = raw;
808        }
809    }
810
811    retArr.push_back(raw);
812    retArr.push_back(val);
813
814    return retArr;
815}
816
817/**********************************************************************/
818// METHOD: parent()
819/// Search the path of a xml tree and return its parent.
820/**
821 * It is the user's responsibility to delete the object when
822 * they are finished using it?, else i need to make this static
823 */
824
825RpLibrary*
826RpLibrary::parent (std::string path)
827{
828    RpLibrary* retLib = NULL;
829    std::string parentPath = "";
830    // std::string::size_type pos = 0;
831    scew_element* ele = NULL;
832    scew_element* retNode = NULL;
833
834    if (!this->root) {
835        // library doesn't exist, do nothing;
836        return NULL;
837    }
838
839    if (path.empty()) {
840        // an empty path returns the parent of the current RpLibrary
841        ele = this->root;
842    }
843    else {
844        // else find the node representing the provided path
845        ele = _find(path,NO_CREATE_PATH);
846    }
847
848    if (ele != NULL) {
849        retNode = scew_element_parent(ele);
850        if (retNode) {
851            // allocate a new rappture library object for the node
852            retLib = new RpLibrary( retNode,this->tree );
853        }
854    }
855    else {
856        // path was not found by _find
857    }
858
859
860    return retLib;
861}
862
863/**********************************************************************/
864// METHOD: copy()
865/// Copy the value from fromPath to toPath.
866//  Copy the value from fromObj.fromPath to toPath
867//  of the current rappture library object. This can copy rappture
868//  library elements within or between xml trees.
869/**
870 */
871
872RpLibrary&
873RpLibrary::copy (std::string toPath, std::string fromPath, RpLibrary* fromObj)
874{
875    RpLibrary* value = NULL;
876    // RpLibrary* child = NULL;
877
878    if (!this->root) {
879        // library doesn't exist, do nothing;
880        // need a good way to raise error, and this is not it.
881        return *this;
882    }
883
884    if (fromObj == NULL) {
885        fromObj = this;
886    }
887
888    value = fromObj->element(fromPath);
889
890    if ( !value ) {
891        // need a good way to raise error, and this is not it.
892        return *this;
893    }
894
895    this->put(toPath, value);
896    delete value;
897
898    return (*this);
899
900}
901
902/**********************************************************************/
903// METHOD: children()
904/// Return the next child of the node located at 'path'
905//
906// The lookup is reset when you send a NULL rpChilNode.
907// User is responsible for deleting returned values
908//
909/**
910 */
911
912/*
913RpLibrary*
914RpLibrary::children (   std::string path,
915                        RpLibrary* rpChildNode,
916                        std::string type,
917                        int* childCount)
918{
919    static std::string old_path = "";
920    static RpLibrary* retLib = NULL;
921    int myChildCount = 0;
922    scew_element* parentNode = NULL;
923    scew_element* childNode = NULL;
924    std::string childName = "";
925
926    if (!this->root) {
927        // library doesn't exist, do nothing;
928        return NULL;
929    }
930
931
932    if (path.empty()) {
933        // an empty path uses the current RpLibrary as parent
934        parentNode = this->root;
935    }
936    else {
937        // check to see if this path is the same as the one set
938        // in the last call to this function.
939        // if so, then we dont need to reset the parentNode
940        //
941        // this check is probably more dependent on rpChildNode
942        // because we want to see if the person want to continue
943        // an old search or start from the beginning of the child list
944        //
945        if ( (path.compare(old_path) == 0) && (rpChildNode != NULL) ) {
946            parentNode = NULL;
947        }
948        // we need to search for a new parentNode
949        else {
950            parentNode = _find(path,NO_CREATE_PATH);
951            if (parentNode == NULL) {
952                // node not found
953                // add error code here
954                return NULL;
955            }
956        }
957    }
958
959    old_path = path;
960
961
962    if (rpChildNode) {
963        childNode = rpChildNode->root;
964    }
965
966    if (parentNode) {
967        myChildCount = scew_element_count(parentNode);
968    }
969
970    if (childCount) {
971        *childCount = myChildCount;
972    }
973
974    // clean up old memory
975    delete retLib;
976
977    if ( (childNode = scew_element_next(parentNode,childNode)) ) {
978
979        if (!type.empty()) {
980            childName = scew_element_name(childNode);
981            // we are searching for a specific child name
982            // keep looking till we find a name that matches the type.
983            // if the current name does not match out search type,
984            // grab the next child and check to see if its null
985            // if its not null, get its name and test for type again
986            while (  (type != childName)
987                  && (childNode = scew_element_next(parentNode,childNode)) ) {
988
989                childName = scew_element_name(childNode);
990            }
991            if (type == childName) {
992                // found a child with a name that matches type
993                retLib = new RpLibrary( childNode,this->tree );
994            }
995            else {
996                // no children with names that match 'type' were found
997                retLib = NULL;
998            }
999        }
1000        else {
1001            retLib = new RpLibrary( childNode,this->tree );
1002        }
1003    }
1004    else {
1005        // somthing happened within scew, get error code and display
1006        // its probable there are no more child elements left to report
1007        retLib = NULL;
1008    }
1009
1010    return retLib;
1011}
1012*/
1013
1014RpLibrary*
1015RpLibrary::children (   std::string path,
1016                        RpLibrary* rpChildNode,
1017                        std::string type,
1018                        int* childCount)
1019{
1020    // this is static for efficency reasons
1021    static std::string old_path = "";
1022    // this was static so user never has to delete the retLib.
1023    // should be replaced by a smart pointer
1024    // static RpLibrary* retLib = NULL;
1025    RpLibrary* retLib = NULL;
1026    int myChildCount = 0;
1027    scew_element* parentNode = NULL;
1028    scew_element* childNode = NULL;
1029    std::string childName = "";
1030
1031    if (!this->root) {
1032        // library doesn't exist, do nothing;
1033        return NULL;
1034    }
1035
1036
1037    // check to see if the last call to this function
1038    // was searching for children of the same path.
1039    if ( (path.compare(old_path) == 0) && (rpChildNode != NULL) ) {
1040        parentNode = NULL;
1041    }
1042    else if (path.empty()) {
1043        // searching for children in a new path.
1044        // an empty path uses the current RpLibrary as parent
1045        parentNode = this->root;
1046    }
1047    else {
1048        // searching for children in a new, non-empty, path.
1049        parentNode = _find(path,NO_CREATE_PATH);
1050        if (parentNode == NULL) {
1051            // node not found
1052            // add error code here
1053            return NULL;
1054        }
1055    }
1056
1057    old_path = path;
1058
1059    if (rpChildNode) {
1060        childNode = rpChildNode->root;
1061    }
1062
1063    if (parentNode) {
1064        myChildCount = scew_element_count(parentNode);
1065        if (childCount) {
1066            *childCount = myChildCount;
1067        }
1068    }
1069
1070    // clean up old memory
1071    // delete retLib;
1072
1073    if ( (childNode = scew_element_next(parentNode,childNode)) ) {
1074
1075        if (!type.empty()) {
1076            childName = scew_element_name(childNode);
1077            // we are searching for a specific child name
1078            // keep looking till we find a name that matches the type.
1079            // if the current name does not match out search type,
1080            // grab the next child and check to see if its null
1081            // if its not null, get its name and test for type again
1082            while (  (type != childName)
1083                  && (childNode = scew_element_next(parentNode,childNode)) ) {
1084
1085                childName = scew_element_name(childNode);
1086            }
1087            if (type == childName) {
1088                // found a child with a name that matches type
1089                retLib = new RpLibrary( childNode,this->tree );
1090            }
1091            else {
1092                // no children with names that match 'type' were found
1093                retLib = NULL;
1094            }
1095        }
1096        else {
1097            retLib = new RpLibrary( childNode,this->tree );
1098        }
1099    }
1100    else {
1101        // somthing happened within scew, get error code and display
1102        // its probable there are no more child elements left to report
1103        retLib = NULL;
1104    }
1105
1106    return retLib;
1107}
1108
1109/**********************************************************************/
1110// METHOD: children()
1111/// Returns a std::list<RpLibrary*> of all children under 'path'
1112//
1113//
1114/**
1115 */
1116
1117RpLibrary&
1118RpLibrary::childCount ( std::string path,
1119                        int* childCount)
1120{
1121    scew_element* parentNode;
1122    int myChildCount = 0;
1123
1124    if (this->root) {
1125
1126        if (path.empty()) {
1127            // an empty path uses the current RpLibrary as parent
1128            parentNode = this->root;
1129        }
1130
1131        if (parentNode) {
1132            myChildCount = scew_element_count(parentNode);
1133        }
1134
1135        if (childCount) {
1136            *childCount = myChildCount;
1137        }
1138
1139    }
1140
1141    return *this;
1142}
1143
1144/**********************************************************************/
1145// METHOD: isNull()
1146/// returns whether this RpLibrary is a valid library node
1147//
1148//
1149/**
1150 */
1151
1152bool
1153RpLibrary::isNull ()
1154{
1155    if (this->root) {
1156        return false;
1157    }
1158
1159    return true;
1160}
1161
1162/**********************************************************************/
1163// METHOD: get()
1164/// Return the string value of the object held at location 'path'
1165/**
1166 */
1167
1168std::string
1169RpLibrary::get (std::string path, int translateFlag)
1170{
1171    return (this->getString(path, translateFlag));
1172}
1173
1174/**********************************************************************/
1175// METHOD: getString()
1176/// Return the string value of the object held at location 'path'
1177/**
1178 */
1179
1180std::string
1181RpLibrary::getString (std::string path, int translateFlag)
1182{
1183    scew_element* retNode = NULL;
1184    XML_Char const* retCStr = NULL;
1185    char* translatedContents = NULL;
1186    std::string retStr = "";
1187    int len = 0;
1188
1189    if (!this->root) {
1190        // library doesn't exist, do nothing;
1191        return std::string("");
1192    }
1193
1194    retNode = _find(path,NO_CREATE_PATH);
1195
1196    if (retNode == NULL) {
1197        // need to raise error
1198        return std::string("");
1199    }
1200
1201    retCStr = scew_element_contents(retNode);
1202
1203    if (!retCStr) {
1204        return std::string("");
1205    }
1206
1207    if (translateFlag == TRANSLATE) {
1208        // translatedContents = new char[strlen(retCStr)+1];
1209        len = strlen(retCStr);
1210        translatedContents = (char*) calloc((len+1),sizeof(char));
1211        if (translatedContents) {
1212            strncpy(translatedContents, retCStr, len);
1213            _translateOut(translatedContents);
1214            retStr = std::string(translatedContents);
1215            // delete[] translatedContents;
1216            free(translatedContents);
1217        }
1218        else {
1219            // error allocating space
1220            return std::string("");
1221        }
1222    }
1223    else {
1224        retStr = std::string(retCStr);
1225    }
1226
1227    return retStr;
1228}
1229
1230/**********************************************************************/
1231// METHOD: getDouble()
1232/// Return the double value of the object held at location 'path'
1233/**
1234 */
1235
1236double
1237RpLibrary::getDouble (std::string path)
1238{
1239    std::string retValStr = "";
1240    double retValDbl = 0;
1241
1242    if (!this->root) {
1243        // library doesn't exist, do nothing;
1244        return retValDbl;
1245    }
1246
1247    retValStr = this->getString(path);
1248    // think about changing this to strtod()
1249    retValDbl = atof(retValStr.c_str());
1250
1251    // how do we raise error?
1252    // currently we depend on getString to raise the error
1253    return retValDbl;
1254}
1255
1256
1257/**********************************************************************/
1258// METHOD: put()
1259/// Put a string value into the xml.
1260/**
1261 */
1262
1263RpLibrary&
1264RpLibrary::put (    std::string path,
1265                    std::string value,
1266                    std::string id,
1267                    int append,
1268                    int translateFlag)
1269{
1270    scew_element* retNode = NULL;
1271    std::string tmpVal = "";
1272    const char* contents = NULL;
1273    std::string translatedContents = "";
1274
1275    if (!this->root) {
1276        // library doesn't exist, do nothing;
1277        return *this;
1278    }
1279
1280    retNode = _find(path,CREATE_PATH);
1281
1282    if (retNode) {
1283
1284        if (append) {
1285            if ( (contents = scew_element_contents(retNode)) ) {
1286                tmpVal = std::string(contents);
1287            }
1288            value = tmpVal + value;
1289        }
1290
1291        if (translateFlag == TRANSLATE) {
1292            _translateIn(value,translatedContents);
1293            scew_element_set_contents(retNode,translatedContents.c_str());
1294        }
1295        else {
1296            scew_element_set_contents(retNode,value.c_str());
1297        }
1298    }
1299
1300    return *this;
1301}
1302
1303/**********************************************************************/
1304// METHOD: put()
1305/// Put a double value into the xml.
1306/**
1307 */
1308
1309RpLibrary&
1310RpLibrary::put ( std::string path, double value, std::string id, int append )
1311{
1312    std::stringstream valStr;
1313
1314    if (!this->root) {
1315        // library doesn't exist, do nothing;
1316        return *this;
1317    }
1318
1319    valStr << value;
1320
1321    return this->put(path,valStr.str(),id,append);
1322}
1323
1324/**********************************************************************/
1325// METHOD: put()
1326/// Put a RpLibrary* value into the xml.
1327/**
1328 *  Append flag adds additional nodes, it does not merge same
1329 *  named nodes together
1330 */
1331
1332RpLibrary&
1333RpLibrary::put ( std::string path, RpLibrary* value, std::string id, int append )
1334{
1335    scew_element* retNode   = NULL;
1336    // scew_element* old_elem  = NULL;
1337    scew_element* new_elem  = NULL;
1338    scew_element* childNode = NULL;
1339    // std::string nodeName    = "";
1340
1341    int retVal = 1;
1342
1343    if (!this->root) {
1344        // library doesn't exist, do nothing;
1345        return *this;
1346    }
1347
1348    // you cannot put a null RpLibrary into the tree
1349    if (!value) {
1350        // need to send back an error saying that user specified a null value
1351        return *this;
1352    }
1353
1354    // nodeName = value->nodeComp();
1355    // old_elem = _find(path+"."+nodeName,NO_CREATE_PATH);
1356
1357    if (!append) {
1358        retNode = _find(path,NO_CREATE_PATH);
1359        if (retNode) {
1360            scew_element_free(retNode);
1361        }
1362        else {
1363            // path did not exist and was not created
1364            // do nothing
1365        }
1366    }
1367
1368    retNode = _find(path,CREATE_PATH);
1369
1370    if (retNode) {
1371        while ( (childNode = scew_element_next(value->root,childNode)) ) {
1372            if ((new_elem = scew_element_copy(childNode))) {
1373                if (scew_element_add_elem(retNode, new_elem)) {
1374                    // maybe we want to count the number of children
1375                    // that we have successfully added?
1376                    retVal = 0;
1377                }
1378                else {
1379                    // adding new element failed
1380                }
1381            }
1382            else {
1383                // copying new element failed
1384            }
1385        }
1386    }
1387    else {
1388        // path did not exist and was not created.
1389    }
1390
1391    return *this;
1392}
1393
1394
1395/**********************************************************************/
1396// METHOD: remove()
1397/// Remove the provided path from this RpLibrary
1398/**
1399 */
1400
1401RpLibrary*
1402RpLibrary::remove ( std::string path )
1403{
1404    scew_element* ele = NULL;
1405    int setNULL = 0;
1406    RpLibrary* retLib = NULL;
1407
1408    if (!this->root) {
1409        // library doesn't exist, do nothing;
1410        return NULL;
1411    }
1412
1413    if ( !path.empty() ) {
1414        ele = _find(path,NO_CREATE_PATH);
1415    }
1416    else {
1417        // telling this function to remove "" is essentially destroying
1418        // the object. most functions will fail after a call like this.
1419        ele = this->root;
1420        setNULL++;
1421    }
1422
1423    if (ele) {
1424        scew_element_free(ele);
1425        if (setNULL != 0) {
1426            // this is the case where user specified an empty path.
1427            // the object is useless, and will be deleted.
1428            this->root = NULL;
1429            retLib = NULL;
1430        }
1431        else {
1432            retLib = this;
1433        }
1434    }
1435
1436    return retLib;
1437}
1438
1439/**********************************************************************/
1440// METHOD: xml()
1441/// Return the xml text held in this RpLibrary
1442/**
1443 */
1444
1445std::string
1446RpLibrary::xml ()
1447{
1448    std::stringstream outString;
1449
1450    if (!this->root) {
1451        // library doesn't exist, do nothing;
1452        return std::string("");
1453    }
1454
1455    outString << "<?xml version=\"1.0\"?>\n";
1456    print_element(this->root, 0, outString);
1457
1458    return outString.str();
1459}
1460
1461/**********************************************************************/
1462// METHOD: nodeType()
1463/// Return the type name of this node
1464/**
1465 */
1466
1467std::string
1468RpLibrary::nodeType ()
1469{
1470    if (!this->root) {
1471        // library doesn't exist, do nothing;
1472        return std::string("");
1473    }
1474
1475    return std::string(scew_element_name(root));
1476}
1477
1478/**********************************************************************/
1479// METHOD: nodeId()
1480/// Return the id of this node.
1481/**
1482 */
1483
1484std::string
1485RpLibrary::nodeId ()
1486{
1487    if (!this->root) {
1488        // library doesn't exist, do nothing;
1489        return std::string("");
1490    }
1491
1492    return _node2name(root);
1493}
1494
1495/**********************************************************************/
1496// METHOD: nodeComp()
1497/// Return the component name of this node.
1498/**
1499 */
1500
1501std::string
1502RpLibrary::nodeComp ()
1503{
1504    if (!this->root) {
1505        // library doesn't exist, do nothing;
1506        return std::string("");
1507    }
1508
1509    return _node2comp(root);
1510}
1511
1512/**********************************************************************/
1513// METHOD: nodePath()
1514/// Return the component name of this node's path.
1515/**
1516 */
1517
1518std::string
1519RpLibrary::nodePath ()
1520{
1521    if (!this->root) {
1522        // library doesn't exist, do nothing;
1523        return std::string("");
1524    }
1525
1526    return _node2path(root);
1527}
1528
1529/*
1530 * ----------------------------------------------------------------------
1531 *  METHOD: result
1532 *
1533 *  Clients call this function at the end of their simulation, to
1534 *  pass the simulation result back to the Rappture GUI.  It writes
1535 *  out the given XML object to a runXXX.xml file, and then writes
1536 *  out the name of that file to stdout.
1537 * ======================================================================
1538 *  AUTHOR:  Michael McLennan, Purdue University
1539 *  Copyright (c) 2004-2005
1540 *  Purdue Research Foundation, West Lafayette, IN
1541 * ======================================================================
1542 */
1543void
1544RpLibrary::result() {
1545    std::stringstream outputFile;
1546    std::fstream file;
1547    std::string xmlText = "";
1548    time_t t = 0;
1549
1550    if (this->root) {
1551        outputFile << "run" << (int)time(&t) << ".xml";
1552        file.open(outputFile.str().c_str(),std::ios::out);
1553
1554        if ( file.is_open() ) {
1555            xmlText = xml();
1556            if (!xmlText.empty()) {
1557                file << xmlText;
1558            }
1559        }
1560        std::cout << "=RAPPTURE-RUN=>" << outputFile.str() << std::endl;
1561    }
1562}
1563
1564/**********************************************************************/
1565// METHOD: print_indent()
1566/// Add indentations to the requested stringstream object.
1567/**
1568 */
1569
1570void
1571RpLibrary::print_indent(unsigned int indent, std::stringstream& outString)
1572{
1573
1574    // keep this around incase you want to use tabs instead of spaces
1575    // while ( (indent--) > 0)
1576    // {
1577    //     outString << "\t";
1578    // }
1579
1580    // keep this around incase you want to use spaces instead of tabs
1581    int cnt = indent*INDENT_SIZE;
1582    while ( (cnt--) > 0)
1583    {
1584        outString << " ";
1585    }
1586
1587}
1588
1589/**********************************************************************/
1590// METHOD: print_attributes()
1591/// Print the attribute names and values for the provided xml node
1592/**
1593 */
1594
1595void
1596RpLibrary::print_attributes(scew_element* element, std::stringstream& outString)
1597{
1598    scew_attribute* attribute = NULL;
1599
1600    if (element != NULL)
1601    {
1602        /**
1603         * Iterates through the element's attribute list, printing the
1604         * pair name-value.
1605         */
1606        attribute = NULL;
1607        while ((attribute = scew_attribute_next(element, attribute)) != NULL)
1608        {
1609            outString << " " << scew_attribute_name(attribute) << "=\"" <<
1610                   scew_attribute_value(attribute) << "\"";
1611        }
1612    }
1613}
1614
1615
1616/**********************************************************************/
1617// METHOD: print_element()
1618/// Print the value of the node and its attributes to a stringstream object
1619/**
1620 */
1621
1622void
1623RpLibrary::print_element(   scew_element* element,
1624                            unsigned int indent,
1625                            std::stringstream& outString    )
1626{
1627    scew_element* child = NULL;
1628    XML_Char const* contents = NULL;
1629
1630    if (element == NULL)
1631    {
1632        return;
1633    }
1634
1635    /**
1636     * Prints the starting element tag with its attributes.
1637     */
1638    print_indent(indent, outString);
1639    outString << "<" << scew_element_name(element);
1640    print_attributes(element,outString);
1641    outString << ">";
1642    contents = scew_element_contents(element);
1643    if (contents == NULL)
1644    {
1645        outString << "\n";
1646    }
1647
1648    /**
1649     * Call print_element function again for each child of the
1650     * current element.
1651     */
1652    child = NULL;
1653    while ((child = scew_element_next(element, child)) != NULL)
1654    {
1655        print_element(child, indent + 1, outString);
1656    }
1657
1658    /* Prints element's content. */
1659    if (contents != NULL)
1660    {
1661        outString << contents;
1662    }
1663    else
1664    {
1665        print_indent(indent, outString);
1666    }
1667
1668    /**
1669     * Prints the closing element tag.
1670     */
1671    outString << "</" << scew_element_name(element) << ">\n" ;
1672}
1673
1674/**********************************************************************/
1675// METHOD: translateIn()
1676/// Translate entity and character reference text coming in from the user
1677/**
1678 */
1679
1680int
1681RpLibrary::_translateIn(std::string& outStr,std::string& translatedStr)
1682{
1683    ERTranslator.appendEscaped(outStr, translatedStr);
1684    return 0;
1685}
1686
1687
1688/**********************************************************************/
1689// METHOD: translateOut()
1690/// Translate entity and character reference text going out to the user
1691/**
1692 */
1693
1694int
1695RpLibrary::_translateOut(char* inStr)
1696{
1697    int newLen = 0;
1698    ERTranslator.TranslateEntityRefs(inStr, &newLen);
1699    return 0;
1700}
Note: See TracBrowser for help on using the repository browser.