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

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

adjusted units code removing const ints in favor of enum values
adjusted library code to include enum values
added time stamp abilities to rappture library's result function
added cplusplus define checks to header files for c and fortran bindings so people can compile with rappture.h

  • Property svn:keywords set to Date Rev URL
File size: 46.3 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 == RPLIB_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: getInt()
1259/// Return the integer value of the object held at location 'path'
1260/**
1261 */
1262
1263int
1264RpLibrary::getInt (std::string path)
1265{
1266    std::string retValStr = "";
1267    int retValInt = 0;
1268
1269    if (!this->root) {
1270        // library doesn't exist, do nothing;
1271        return retValInt;
1272    }
1273
1274    retValStr = this->getString(path);
1275    // think about changing this to strtod()
1276    retValInt = atoi(retValStr.c_str());
1277
1278    // how do we raise error?
1279    // currently we depend on getString to raise the error
1280    return retValInt;
1281}
1282
1283
1284/**********************************************************************/
1285// METHOD: getBool()
1286/// Return the boolean value of the object held at location 'path'
1287/**
1288 */
1289
1290bool
1291RpLibrary::getBool (std::string path)
1292{
1293    std::string retValStr = "";
1294    bool retValBool = false;
1295    int retValLen = 0;
1296
1297    if (!this->root) {
1298        // library doesn't exist, do nothing;
1299        return retValBool;
1300    }
1301
1302    retValStr = this->getString(path);
1303    transform (retValStr.begin(),retValStr.end(),retValStr.begin(),tolower);
1304    retValLen = retValStr.length();
1305
1306    if ((retValStr.compare(0,retValLen,"1",0,retValLen) == 0  )   ||
1307        (retValStr.compare(0,retValLen,"yes",0,retValLen) == 0 )  ||
1308        (retValStr.compare(0,retValLen,"true",0,retValLen) == 0 ) ||
1309        (retValStr.compare(0,retValLen,"on",0,retValLen) == 0))
1310    {
1311        retValBool = true;
1312    }
1313    else if((retValStr.compare(0,retValLen,"0",0,retValLen) == 0  )   ||
1314            (retValStr.compare(0,retValLen,"no",0,retValLen) == 0 )  ||
1315            (retValStr.compare(0,retValLen,"false",0,retValLen) == 0 ) ||
1316            (retValStr.compare(0,retValLen,"off",0,retValLen) == 0))
1317    {
1318        retValBool = false;
1319    }
1320    else {
1321        // default to false?
1322        retValBool = false;
1323    }
1324
1325    // how do we raise error?
1326    // currently we depend on getString to raise the error
1327    return retValBool;
1328}
1329
1330
1331/**********************************************************************/
1332// METHOD: put()
1333/// Put a string value into the xml.
1334/**
1335 */
1336
1337RpLibrary&
1338RpLibrary::put (    std::string path,
1339                    std::string value,
1340                    std::string id,
1341                    int append,
1342                    int translateFlag)
1343{
1344    scew_element* retNode = NULL;
1345    std::string tmpVal = "";
1346    const char* contents = NULL;
1347    std::string translatedContents = "";
1348
1349    if (!this->root) {
1350        // library doesn't exist, do nothing;
1351        return *this;
1352    }
1353
1354    retNode = _find(path,CREATE_PATH);
1355
1356    if (retNode) {
1357
1358        if (append == RPLIB_APPEND) {
1359            if ( (contents = scew_element_contents(retNode)) ) {
1360                tmpVal = std::string(contents);
1361            }
1362            value = tmpVal + value;
1363        }
1364
1365        if (translateFlag == RPLIB_TRANSLATE) {
1366            _translateIn(value,translatedContents);
1367            scew_element_set_contents(retNode,translatedContents.c_str());
1368        }
1369        else {
1370            scew_element_set_contents(retNode,value.c_str());
1371        }
1372    }
1373
1374    return *this;
1375}
1376
1377/**********************************************************************/
1378// METHOD: put()
1379/// Put a double value into the xml.
1380/**
1381 */
1382
1383RpLibrary&
1384RpLibrary::put ( std::string path, double value, std::string id, int append )
1385{
1386    std::stringstream valStr;
1387
1388    if (!this->root) {
1389        // library doesn't exist, do nothing;
1390        return *this;
1391    }
1392
1393    valStr << value;
1394
1395    return this->put(path,valStr.str(),id,append);
1396}
1397
1398/**********************************************************************/
1399// METHOD: put()
1400/// Put a RpLibrary* value into the xml.
1401/**
1402 *  Append flag adds additional nodes, it does not merge same
1403 *  named nodes together
1404 */
1405
1406RpLibrary&
1407RpLibrary::put ( std::string path, RpLibrary* value, std::string id, int append )
1408{
1409    scew_element* retNode   = NULL;
1410    // scew_element* old_elem  = NULL;
1411    scew_element* new_elem  = NULL;
1412    scew_element* childNode = NULL;
1413    // std::string nodeName    = "";
1414
1415    int retVal = 1;
1416
1417    if (!this->root) {
1418        // library doesn't exist, do nothing;
1419        return *this;
1420    }
1421
1422    // you cannot put a null RpLibrary into the tree
1423    if (!value) {
1424        // need to send back an error saying that user specified a null value
1425        return *this;
1426    }
1427
1428    // nodeName = value->nodeComp();
1429    // old_elem = _find(path+"."+nodeName,NO_CREATE_PATH);
1430
1431    if (append == RPLIB_OVERWRITE) {
1432        retNode = _find(path,NO_CREATE_PATH);
1433        if (retNode) {
1434            scew_element_free(retNode);
1435        }
1436        else {
1437            // path did not exist and was not created
1438            // do nothing
1439        }
1440    }
1441
1442    retNode = _find(path,CREATE_PATH);
1443
1444    if (retNode) {
1445        while ( (childNode = scew_element_next(value->root,childNode)) ) {
1446            if ((new_elem = scew_element_copy(childNode))) {
1447                if (scew_element_add_elem(retNode, new_elem)) {
1448                    // maybe we want to count the number of children
1449                    // that we have successfully added?
1450                    retVal = 0;
1451                }
1452                else {
1453                    // adding new element failed
1454                }
1455            }
1456            else {
1457                // copying new element failed
1458            }
1459        }
1460    }
1461    else {
1462        // path did not exist and was not created.
1463    }
1464
1465    return *this;
1466}
1467
1468
1469/**********************************************************************/
1470// METHOD: remove()
1471/// Remove the provided path from this RpLibrary
1472/**
1473 */
1474
1475RpLibrary*
1476RpLibrary::remove ( std::string path )
1477{
1478    scew_element* ele = NULL;
1479    int setNULL = 0;
1480    RpLibrary* retLib = NULL;
1481
1482    if (!this->root) {
1483        // library doesn't exist, do nothing;
1484        return NULL;
1485    }
1486
1487    if ( !path.empty() ) {
1488        ele = _find(path,NO_CREATE_PATH);
1489    }
1490    else {
1491        // telling this function to remove "" is essentially destroying
1492        // the object. most functions will fail after a call like this.
1493        ele = this->root;
1494        setNULL++;
1495    }
1496
1497    if (ele) {
1498        scew_element_free(ele);
1499        if (setNULL != 0) {
1500            // this is the case where user specified an empty path.
1501            // the object is useless, and will be deleted.
1502            this->root = NULL;
1503            retLib = NULL;
1504        }
1505        else {
1506            retLib = this;
1507        }
1508    }
1509
1510    return retLib;
1511}
1512
1513/**********************************************************************/
1514// METHOD: xml()
1515/// Return the xml text held in this RpLibrary
1516/**
1517 */
1518
1519std::string
1520RpLibrary::xml ()
1521{
1522    std::stringstream outString;
1523
1524    if (!this->root) {
1525        // library doesn't exist, do nothing;
1526        return std::string("");
1527    }
1528
1529    outString << "<?xml version=\"1.0\"?>\n";
1530    print_element(this->root, 0, outString);
1531
1532    return outString.str();
1533}
1534
1535/**********************************************************************/
1536// METHOD: nodeType()
1537/// Return the type name of this node
1538/**
1539 */
1540
1541std::string
1542RpLibrary::nodeType ()
1543{
1544    if (!this->root) {
1545        // library doesn't exist, do nothing;
1546        return std::string("");
1547    }
1548
1549    return std::string(scew_element_name(root));
1550}
1551
1552/**********************************************************************/
1553// METHOD: nodeId()
1554/// Return the id of this node.
1555/**
1556 */
1557
1558std::string
1559RpLibrary::nodeId ()
1560{
1561    if (!this->root) {
1562        // library doesn't exist, do nothing;
1563        return std::string("");
1564    }
1565
1566    return _node2name(root);
1567}
1568
1569/**********************************************************************/
1570// METHOD: nodeComp()
1571/// Return the component name of this node.
1572/**
1573 */
1574
1575std::string
1576RpLibrary::nodeComp ()
1577{
1578    if (!this->root) {
1579        // library doesn't exist, do nothing;
1580        return std::string("");
1581    }
1582
1583    return _node2comp(root);
1584}
1585
1586/**********************************************************************/
1587// METHOD: nodePath()
1588/// Return the component name of this node's path.
1589/**
1590 */
1591
1592std::string
1593RpLibrary::nodePath ()
1594{
1595    if (!this->root) {
1596        // library doesn't exist, do nothing;
1597        return std::string("");
1598    }
1599
1600    return _node2path(root);
1601}
1602
1603/*
1604 * ----------------------------------------------------------------------
1605 *  METHOD: result
1606 *
1607 *  Clients call this function at the end of their simulation, to
1608 *  pass the simulation result back to the Rappture GUI.  It writes
1609 *  out the given XML object to a runXXX.xml file, and then writes
1610 *  out the name of that file to stdout.
1611 * ======================================================================
1612 *  AUTHOR:  Michael McLennan, Purdue University
1613 *  Copyright (c) 2004-2005
1614 *  Purdue Research Foundation, West Lafayette, IN
1615 * ======================================================================
1616 */
1617void
1618RpLibrary::result() {
1619    std::stringstream outputFile;
1620    std::fstream file;
1621    std::string xmlText = "";
1622    time_t t = 0;
1623    struct tm* timeinfo = NULL;
1624    std::string timestamp = "";
1625
1626    if (this->root) {
1627        outputFile << "run" << (int)time(&t) << ".xml";
1628        file.open(outputFile.str().c_str(),std::ios::out);
1629
1630        put("tool.repository.rappture.date","$Date: 2006-12-09 08:56:11 +0000 (Sat, 09 Dec 2006) $");
1631        put("tool.repository.rappture.revision","$Rev: 554 $");
1632        put("tool.repository.rappture.url","$URL: trunk/src/core/RpLibrary.cc $");
1633
1634        // generate a timestamp for the run file
1635        timeinfo = localtime(&t);
1636        timestamp = std::string(ctime(&t));
1637        // erase the 24th character because it is a newline
1638        timestamp.erase(24);
1639        // concatinate the timezone
1640        timestamp.append(" ");
1641        timestamp.append(timeinfo->tm_zone);
1642
1643        // add the timestamp to the run file
1644        put("output.time", timestamp);
1645
1646        if ( file.is_open() ) {
1647            xmlText = xml();
1648            if (!xmlText.empty()) {
1649                file << xmlText;
1650            }
1651        }
1652        std::cout << "=RAPPTURE-RUN=>" << outputFile.str() << std::endl;
1653    }
1654}
1655
1656/**********************************************************************/
1657// METHOD: print_indent()
1658/// Add indentations to the requested stringstream object.
1659/**
1660 */
1661
1662void
1663RpLibrary::print_indent(unsigned int indent, std::stringstream& outString)
1664{
1665
1666    // keep this around incase you want to use tabs instead of spaces
1667    // while ( (indent--) > 0)
1668    // {
1669    //     outString << "\t";
1670    // }
1671
1672    // keep this around incase you want to use spaces instead of tabs
1673    int cnt = indent*INDENT_SIZE;
1674    while ( (cnt--) > 0)
1675    {
1676        outString << " ";
1677    }
1678
1679}
1680
1681/**********************************************************************/
1682// METHOD: print_attributes()
1683/// Print the attribute names and values for the provided xml node
1684/**
1685 */
1686
1687void
1688RpLibrary::print_attributes(scew_element* element, std::stringstream& outString)
1689{
1690    scew_attribute* attribute = NULL;
1691
1692    if (element != NULL)
1693    {
1694        /**
1695         * Iterates through the element's attribute list, printing the
1696         * pair name-value.
1697         */
1698        attribute = NULL;
1699        while ((attribute = scew_attribute_next(element, attribute)) != NULL)
1700        {
1701            outString << " " << scew_attribute_name(attribute) << "=\"" <<
1702                   scew_attribute_value(attribute) << "\"";
1703        }
1704    }
1705}
1706
1707
1708/**********************************************************************/
1709// METHOD: print_element()
1710/// Print the value of the node and its attributes to a stringstream object
1711/**
1712 */
1713
1714void
1715RpLibrary::print_element(   scew_element* element,
1716                            unsigned int indent,
1717                            std::stringstream& outString    )
1718{
1719    scew_element* child = NULL;
1720    XML_Char const* contents = NULL;
1721
1722    if (element == NULL)
1723    {
1724        return;
1725    }
1726
1727    /**
1728     * Prints the starting element tag with its attributes.
1729     */
1730    print_indent(indent, outString);
1731    outString << "<" << scew_element_name(element);
1732    print_attributes(element,outString);
1733    outString << ">";
1734    contents = scew_element_contents(element);
1735    if (contents == NULL)
1736    {
1737        outString << "\n";
1738    }
1739
1740    /**
1741     * Call print_element function again for each child of the
1742     * current element.
1743     */
1744    child = NULL;
1745    while ((child = scew_element_next(element, child)) != NULL)
1746    {
1747        print_element(child, indent + 1, outString);
1748    }
1749
1750    /* Prints element's content. */
1751    if (contents != NULL)
1752    {
1753        outString << contents;
1754    }
1755    else
1756    {
1757        print_indent(indent, outString);
1758    }
1759
1760    /**
1761     * Prints the closing element tag.
1762     */
1763    outString << "</" << scew_element_name(element) << ">\n" ;
1764}
1765
1766/**********************************************************************/
1767// METHOD: translateIn()
1768/// Translate entity and character reference text coming in from the user
1769/**
1770 */
1771
1772int
1773RpLibrary::_translateIn(std::string& outStr,std::string& translatedStr)
1774{
1775    ERTranslator.appendEscaped(outStr, translatedStr);
1776    return 0;
1777}
1778
1779
1780/**********************************************************************/
1781// METHOD: translateOut()
1782/// Translate entity and character reference text going out to the user
1783/**
1784 */
1785
1786int
1787RpLibrary::_translateOut(char* inStr)
1788{
1789    int newLen = 0;
1790    ERTranslator.TranslateEntityRefs(inStr, &newLen);
1791    return 0;
1792}
Note: See TracBrowser for help on using the repository browser.