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

Last change on this file since 365 was 365, checked in by dkearney, 19 years ago

fixes for tcl bindings.

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