Statistics
| Branch: | Revision:

root / src / envir / cxmldoccache.cc @ master

History | View | Annotate | Download (4.88 KB)

1
//==========================================================================
2
//  XMLDOCCACHE.CC - part of
3
//                     OMNeT++/OMNEST
4
//             Discrete System Simulation in C++
5
//
6
//  Author: Andras Varga
7
//
8
//==========================================================================
9

    
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992-2008 Andras Varga
12
  Copyright (C) 2006-2008 OpenSim Ltd.
13

14
  This file is distributed WITHOUT ANY WARRANTY. See the file
15
  `license' for details on this and other legal matters.
16
*--------------------------------------------------------------*/
17

    
18
#include "cobject.h"
19
#include "cxmldoccache.h"
20
#include "cxmlelement.h"
21
#include "cexception.h"
22
#include "fileutil.h"
23
#include "../nedxml/saxparser.h"
24

    
25
USING_NAMESPACE
26

    
27

    
28
// We depend on WITH_NETBUILDER because it brings the nedxml library which
29
// contains the XML parser. TBD XML parser should be an independent library
30
#ifdef WITH_NETBUILDER
31

    
32
/**
33
 * SAX handler (to be used with SAXParser) that builds a cXMLElement tree.
34
 */
35
class cXMLSAXHandler : public SAXHandler
36
{
37
    cXMLElement *root;
38
    cXMLElement *current;
39
    const char *sourcefilename;
40

    
41
  public:
42
    /**
43
     * Constructor. Filename is necessary to create correct src-loc info.
44
     */
45
    cXMLSAXHandler(const char *filename);
46

    
47
    /**
48
     * Destructor
49
     */
50
    virtual ~cXMLSAXHandler();
51

    
52
    /**
53
     * Returns the object tree that was built up during XML parsing.
54
     */
55
    virtual cXMLElement *getTree();
56

    
57
    /** @name SAX event handlers */
58
    //@{
59
    virtual void startElement(const char *name, const char **atts);
60
    virtual void endElement(const char *name);
61
    virtual void characterData(const char *s, int len);
62
    virtual void processingInstruction(const char *target, const char *data);
63
    virtual void comment(const char *data);
64
    virtual void startCdataSection();
65
    virtual void endCdataSection();
66
    //@}
67
};
68

    
69
//---
70

    
71
cXMLSAXHandler::cXMLSAXHandler(const char *fname)
72
{
73
    root = current = new cXMLElement("/", "", NULL); // "Document node" (used as sort of a sentry)
74
    sourcefilename = fname;
75
}
76

    
77
cXMLSAXHandler::~cXMLSAXHandler()
78
{
79
    delete root;
80
}
81

    
82
cXMLElement *cXMLSAXHandler::getTree()
83
{
84
    cXMLElement *tree = root;
85
    root = current = new cXMLElement("/", "", NULL);
86
    return tree;
87
}
88

    
89
void cXMLSAXHandler::startElement(const char *name, const char **atts)
90
{
91
    // source location
92
    char srcloc[500];
93
    sprintf(srcloc,"%s:%d", sourcefilename, parser->getCurrentLineNumber());
94

    
95
    // create element
96
    cXMLElement *node = new cXMLElement(name, srcloc, current);
97
    current = node;
98

    
99
    // set attributes
100
    for (int i=0; atts && atts[i]; i+=2)
101
        node->setAttribute(atts[i], atts[i+1]);
102
}
103

    
104
void cXMLSAXHandler::endElement(const char *name)
105
{
106
    current = current->getParentNode();
107
}
108

    
109
void cXMLSAXHandler::characterData(const char *s, int len)
110
{
111
    current->appendNodeValue(s, len);
112
}
113

    
114
void cXMLSAXHandler::processingInstruction(const char *target, const char *data)
115
{
116
    // ignore
117
}
118

    
119
void cXMLSAXHandler::comment(const char *data)
120
{
121
    // ignore
122
}
123

    
124
void cXMLSAXHandler::startCdataSection()
125
{
126
    // ignore
127
}
128

    
129
void cXMLSAXHandler::endCdataSection()
130
{
131
    // ignore
132
}
133

    
134
#endif  //WITH_NETBUILDER
135

    
136
//=========================================================
137

    
138
cXMLDocCache::cXMLDocCache()
139
{
140
}
141

    
142
cXMLDocCache::~cXMLDocCache()
143
{
144
    for (XMLDocMap::iterator i=cache.begin(); i!=cache.end(); ++i)
145
        delete i->second;
146
}
147

    
148
cXMLElement *cXMLDocCache::parseDocument(const char *filename)
149
{
150
#ifndef WITH_NETBUILDER
151
    throw cRuntimeError("Cannot load `%s': XML config file support currently requires "
152
                        "WITH_NETBUILDER option (check configure.user or configuser.vc, then "
153
                        "rebuild OMNeT++)", filename);
154
#else
155
    cXMLSAXHandler sh(filename);
156
    SAXParser parser;
157

    
158
    parser.setHandler(&sh);
159
    bool ok = parser.parse(filename);
160
    if (!ok)
161
        throw cRuntimeError("Error reading `%s': %s", filename, parser.getErrorMessage());
162

    
163
    return sh.getTree();
164
#endif
165
}
166

    
167
cXMLElement *cXMLDocCache::getDocument(const char *filename)
168
{
169
    // if found, return it from cache
170
    XMLDocMap::iterator it = cache.find(std::string(filename));
171
    if (it != cache.end())
172
        return it->second;
173

    
174
    // load and store in cache
175
    // TODO resolve <xi:include>
176
    cXMLElement *documentnode = parseDocument(filename);
177

    
178
    std::string key = tidyFilename(toAbsolutePath(filename).c_str());
179
    cache[key] = documentnode;
180

    
181
    return documentnode;
182
}
183

    
184
void cXMLDocCache::forgetDocument(const char *filename)
185
{
186
    std::string key = tidyFilename(toAbsolutePath(filename).c_str());
187

    
188
    XMLDocMap::iterator it = cache.find(key);
189
    if (it != cache.end())
190
    {
191
        cXMLElement *node = it->second;
192
        cache.erase(it);
193
        delete node;
194
    }
195
}
196

    
197
void cXMLDocCache::flushCache()
198
{
199
    for (XMLDocMap::iterator i=cache.begin(); i!=cache.end(); ++i)
200
        delete i->second;
201
    cache.clear();
202
}
203