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

Last change on this file since 315 was 224, checked in by dkearney, 18 years ago

added support for following functions in rappture core
diff
value
entities
added support for diff function in tcl bindings.

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