~ubuntu-branches/ubuntu/quantal/kde-runtime/quantal

« back to all changes in this revision

Viewing changes to nepomuk/services/storage/rcgen/nepomuk-simpleresource-rcgen.py

  • Committer: Package Import Robot
  • Author(s): Philip Muškovac
  • Date: 2012-06-03 21:50:00 UTC
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20120603215000-vn7oarsq0ynrydj5
Tags: upstream-4.8.80
Import upstream version 4.8.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# -*- coding: utf-8 -*-
3
 
 
4
 
## This file is part of the Nepomuk KDE project.
5
 
## Copyright (C) 2011 Sebastian Trueg <trueg@kde.org>
6
 
## Copyright (C) 2011 Serebriyskiy Artem <v.for.vandal@gmail.com>
7
 
##
8
 
## This library is free software; you can redistribute it and/or
9
 
## modify it under the terms of the GNU Lesser General Public
10
 
## License as published by the Free Software Foundation; either
11
 
## version 2.1 of the License, or (at your option) version 3, or any
12
 
## later version accepted by the membership of KDE e.V. (or its
13
 
## successor approved by the membership of KDE e.V.), which shall
14
 
## act as a proxy defined in Section 6 of version 3 of the license.
15
 
##
16
 
## This library is distributed in the hope that it will be useful,
17
 
## but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
 
## Lesser General Public License for more details.
20
 
##
21
 
## You should have received a copy of the GNU Lesser General Public
22
 
## License along with this library.  If not, see <http://www.gnu.org/licenses/>.
23
 
 
24
 
 
25
 
import argparse
26
 
import sys
27
 
import os, errno
28
 
from PyKDE4.soprano import Soprano
29
 
from PyQt4 import QtCore
30
 
 
31
 
output_path = os.getcwd()
32
 
verbose = True
33
 
 
34
 
# A list of C++ reserved keywords which we need to handle
35
 
cppKeywords = ['class', 'int', 'float', 'double']
36
 
 
37
 
def normalizeName(name):
38
 
    "Normalize a class or property name to be used as a C++ entity."
39
 
    name.replace('-', '_')
40
 
    name.replace('.', '_')
41
 
    return name
42
 
 
43
 
def extractNameFromUri(uri):
44
 
    "Extract the class or property name from an entity URI. This is the last section of the URI"
45
 
    name = uri.toString().mid(uri.toString().lastIndexOf(QtCore.QRegExp('[#/:]'))+1)
46
 
    return normalizeName(name)
47
 
 
48
 
def makeFancy(name, cardinality):
49
 
    if name.startsWith("has"):
50
 
        name = name[3].toLower() + name.mid(4)
51
 
    if cardinality != 1:
52
 
        if name.endsWith('s'):
53
 
            name = name + 'es'
54
 
        else:
55
 
            name = name + 's'
56
 
 
57
 
    return normalizeName(name)
58
 
 
59
 
def extractOntologyName(uri):
60
 
    "The name of the ontology is typically the section before the name of the entity"
61
 
    return uri.toString().section(QtCore.QRegExp('[#/:]'), -2, -2)
62
 
 
63
 
def mkdir_p(path):
64
 
    "Create a folder and all its missing parent folders"
65
 
    try:
66
 
        os.makedirs(path)
67
 
    except OSError as exc: # Python >2.5
68
 
        if exc.errno == errno.EEXIST:
69
 
            pass
70
 
        else: raise
71
 
 
72
 
def typeString(rdfType, cardinality):
73
 
    """
74
 
    Construct the C++/Qt type to be used for the given type and cardinality.
75
 
    Uses QUrl for all non-literal types
76
 
    """
77
 
    if (rdfType == Soprano.Vocabulary.XMLSchema.string() or rdfType == Soprano.Vocabulary.RDFS.Literal()) and cardinality != 1:
78
 
        return 'QStringList'
79
 
 
80
 
    simpleType = ''
81
 
    if rdfType == Soprano.Vocabulary.XMLSchema.integer(): simpleType = "qint64"
82
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.negativeInteger(): simpleType = "qint64"
83
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.nonNegativeInteger(): simpleType = "quint64"
84
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.xsdLong(): simpleType = "qint64"
85
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.unsignedLong(): simpleType = "quint64"
86
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.xsdInt(): simpleType = "qint32"
87
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.unsignedInt(): simpleType = "quint32"
88
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.xsdShort(): simpleType = "qint16"
89
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.unsignedShort(): simpleType = "quint16"
90
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.xsdFloat(): simpleType = "double"
91
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.xsdDouble(): simpleType = "double"
92
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.boolean(): simpleType = "bool"
93
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.date(): simpleType = "QDate"
94
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.time(): simpleType = "QTime"
95
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.dateTime(): simpleType = "QDateTime"
96
 
    elif rdfType == Soprano.Vocabulary.XMLSchema.string(): simpleType = "QString"
97
 
    elif rdfType == Soprano.Vocabulary.RDFS.Literal(): simpleType = "QString"
98
 
    else: simpleType = 'QUrl'
99
 
 
100
 
    if cardinality != 1:
101
 
        return 'QList<%s>' % simpleType
102
 
    else:
103
 
        return simpleType
104
 
 
105
 
 
106
 
class OntologyParser():
107
 
    def __init__(self):
108
 
        self.model = Soprano.createModel()
109
 
 
110
 
    def parseFile(self, path):
111
 
        parser = Soprano.PluginManager.instance().discoverParserForSerialization(Soprano.SerializationTrig)
112
 
        if not parser:
113
 
            return False
114
 
        it = parser.parseFile(path, QtCore.QUrl("dummy"), Soprano.SerializationTrig)
115
 
        while it.next():
116
 
            self.model.addStatement(it.current())
117
 
        if parser.lastError():
118
 
            return False;
119
 
 
120
 
        return True
121
 
 
122
 
    def writeAll(self):
123
 
 
124
 
        # add rdfs:Resource as domain for all properties without a domain
125
 
        query = 'select ?p where { ?p a %s . OPTIONAL { ?p %s ?d . } . FILTER(!BOUND(?d)) . }' \
126
 
                 % (Soprano.Node.resourceToN3(Soprano.Vocabulary.RDF.Property()), \
127
 
                         Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.domain()))
128
 
        nodes = self.model.executeQuery(query, Soprano.Query.QueryLanguageSparql).iterateBindings(0).allNodes()
129
 
        for p in nodes:
130
 
            self.model.addStatement(p, Soprano.Node(Soprano.Vocabulary.RDFS.domain()), Soprano.Node(Soprano.Vocabulary.RDFS.Resource()))
131
 
        
132
 
        # cache a few values we need more than once
133
 
        self.rdfsResourceProperties = self.getPropertiesForClass(Soprano.Vocabulary.RDFS.Resource())
134
 
 
135
 
        query = 'select distinct ?uri ?label ?comment where {{ ?uri a {0} . ?uri {1} ?label . OPTIONAL {{ ?uri {2} ?comment . }} . }}' \
136
 
            .format(Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.Class()), \
137
 
                         Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.label()), \
138
 
                         Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.comment()))
139
 
        it = self.model.executeQuery(query, Soprano.Query.QueryLanguageSparql)
140
 
        
141
 
        while it.next():
142
 
            uri = it['uri'].uri()
143
 
            if verbose:
144
 
                print "Parsing class: ", uri
145
 
            ns = self.getNamespaceAbbreviationForUri(uri)
146
 
            name = extractNameFromUri(uri)
147
 
            self.writeHeader(uri, ns, name, it['label'].toString(), it['comment'].toString())
148
 
            print "\n\n"
149
 
 
150
 
    def getNamespaceAbbreviationForUri(self, uri):
151
 
        query = "select ?ns where { graph ?g { %s ?p ?o . } . ?g %s ?ns . } LIMIT 1" \
152
 
            % (Soprano.Node.resourceToN3(uri), \
153
 
               Soprano.Node.resourceToN3(Soprano.Vocabulary.NAO.hasDefaultNamespaceAbbreviation()))
154
 
        it = self.model.executeQuery(query, Soprano.Query.QueryLanguageSparql)
155
 
        if it.next():
156
 
            return it[0].toString().toLower()
157
 
        else:
158
 
            return extractOntologyName(uri)
159
 
 
160
 
    def getParentClasses(self, uri):
161
 
        """
162
 
        Returns a dict which maps parent class URIs to a dict containing keys 'ns' and 'name'
163
 
        Only parent classes that are actually generated are returned.
164
 
        """
165
 
        query = "select distinct ?uri where {{ {0} {1} ?uri . ?uri a {2} . }}" \
166
 
             .format(Soprano.Node.resourceToN3(uri), \
167
 
                          Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.subClassOf()), \
168
 
                          Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.Class()))
169
 
        it = self.model.executeQuery(query, Soprano.Query.QueryLanguageSparql)
170
 
        classes = {}
171
 
        while it.next():
172
 
            puri = it['uri'].uri()
173
 
            if puri != Soprano.Vocabulary.RDFS.Resource():
174
 
                cd = {}
175
 
                cd['ns'] = self.getNamespaceAbbreviationForUri(puri)
176
 
                cd['name'] = extractNameFromUri(puri)
177
 
                classes[puri.toString()] = cd
178
 
        return classes
179
 
 
180
 
    def getFullParentHierarchy(self, uri, currentParents, result):
181
 
        """
182
 
        Returns a list of dicts containing keys 'ns' and 'name'.
183
 
        currentParents is a running variable used to avoid endless loops when recursing. It should
184
 
        always be set to the empty list [].
185
 
        result is another running variable which stores the final result set. It should also be set
186
 
        to the empty list [].
187
 
        """
188
 
        # we perform a depth-first search for the most general type
189
 
        directParents = self.getParentClasses(uri)
190
 
        for p in directParents.keys():
191
 
            if not p in currentParents:
192
 
                currentParents.append(p)
193
 
                self.getFullParentHierarchy(QtCore.QUrl(p), currentParents, result)
194
 
                result.append(directParents[p])
195
 
        return result
196
 
 
197
 
    def getPropertiesForClass(self, uri):
198
 
        query = "select distinct ?p ?range ?comment ?c ?mc where { ?p a %s . ?p %s %s . ?p %s ?range . OPTIONAL { ?p %s ?comment . } . OPTIONAL { ?p %s ?c . } . OPTIONAL { ?p %s ?mc . } . }" \
199
 
            % (Soprano.Node.resourceToN3(Soprano.Vocabulary.RDF.Property()),
200
 
               Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.domain()),
201
 
               Soprano.Node.resourceToN3(uri),
202
 
               Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.range()),
203
 
               Soprano.Node.resourceToN3(Soprano.Vocabulary.RDFS.comment()),
204
 
               Soprano.Node.resourceToN3(Soprano.Vocabulary.NRL.cardinality()),
205
 
               Soprano.Node.resourceToN3(Soprano.Vocabulary.NRL.maxCardinality()))
206
 
        it = self.model.executeQuery(query, Soprano.Query.QueryLanguageSparql)
207
 
        #print "Property query done."
208
 
        properties = {}
209
 
        while it.next():
210
 
            p = it['p'].uri()
211
 
            r = it['range'].uri()
212
 
            comment = it['comment'].toString()
213
 
            c = 0
214
 
            if it['c'].isValid():
215
 
                c = it['c'].literal().toInt()
216
 
            else:
217
 
                c = it['mc'].literal().toInt()
218
 
            properties[p] = dict([('range', r), ('cardinality', c), ('comment', comment)])
219
 
        return properties
220
 
 
221
 
    def writeComment(self, theFile, text, indent):
222
 
        maxLine = 50;
223
 
 
224
 
        theFile.write(' ' * indent*4)
225
 
        theFile.write("/**\n")
226
 
        theFile.write(' ' * (indent*4+1))
227
 
        theFile.write("* ")
228
 
 
229
 
        words = QtCore.QString(text).split( QtCore.QRegExp("\\s"), QtCore.QString.SkipEmptyParts )
230
 
        cnt = 0;
231
 
        for i in range(words.count()):
232
 
            if cnt >= maxLine:
233
 
                theFile.write('\n')
234
 
                theFile.write(' ' * (indent*4+1))
235
 
                theFile.write("* ")
236
 
                cnt = 0;
237
 
            theFile.write(words[i])
238
 
            theFile.write(' ')
239
 
            cnt += words[i].length()
240
 
 
241
 
        theFile.write('\n')
242
 
        theFile.write(' ' * (indent*4+1))
243
 
        theFile.write("*/\n")
244
 
 
245
 
    def writeGetter(self, theFile, prop, name, propRange, cardinality):
246
 
        fancyName = makeFancy(name, cardinality)
247
 
        if fancyName in cppKeywords:
248
 
            fancyName = 'get' + fancyName[0].toUpper() + fancyName.mid(1)
249
 
        theFile.write('    %s %s() const {\n' % (typeString(propRange, cardinality), fancyName))
250
 
        theFile.write('        %s value;\n' % typeString(propRange, cardinality))
251
 
        if cardinality == 1:
252
 
            theFile.write('        if(contains(QUrl::fromEncoded("%s", QUrl::StrictMode)))\n' % prop.toString())
253
 
            theFile.write('            value = property(QUrl::fromEncoded("{0}", QUrl::StrictMode)).first().value<{1}>();\n'.format(prop.toString(), typeString(propRange, 1)))
254
 
        else:
255
 
            theFile.write('        foreach(const QVariant& v, property(QUrl::fromEncoded("%s", QUrl::StrictMode)))\n' % prop.toString())
256
 
            theFile.write('            value << v.value<{0}>();\n'.format(typeString(propRange, 1)))
257
 
        theFile.write('        return value;\n')
258
 
        theFile.write('    }\n')
259
 
 
260
 
    def writeSetter(self, theFile, prop, name, propRange, cardinality):
261
 
        theFile.write('    void set%s%s(const %s& value) {\n' % (makeFancy(name, cardinality)[0].toUpper(), makeFancy(name, cardinality).mid(1), typeString(propRange, cardinality)))
262
 
        theFile.write('        QVariantList values;\n')
263
 
        if cardinality == 1:
264
 
            theFile.write('        values << value;\n')
265
 
        else:
266
 
             theFile.write('        foreach(const %s& v, value)\n' % typeString(propRange, 1))
267
 
             theFile.write('            values << v;\n')
268
 
        theFile.write('        setProperty(QUrl::fromEncoded("%s", QUrl::StrictMode), values);\n' % prop.toString())
269
 
        theFile.write('    }\n')
270
 
 
271
 
    def writeAdder(self, theFile, prop, name, propRange, cardinality):
272
 
        theFile.write('    void add%s%s(const %s& value) {\n' % (makeFancy(name, 1)[0].toUpper(), makeFancy(name, 1).mid(1), typeString(propRange, 1)))
273
 
        theFile.write('        addProperty(QUrl::fromEncoded("%s", QUrl::StrictMode), value);\n' % prop.toString())
274
 
        theFile.write('    }\n')
275
 
 
276
 
    def writeHeader(self, uri, nsAbbr, className, label, comment):
277
 
        # Construct paths
278
 
        relative_path = nsAbbr + '/' + className.toLower() + '.h'
279
 
        folder = output_path + '/' + nsAbbr
280
 
        filePath = output_path + '/' + relative_path
281
 
 
282
 
        if verbose:
283
 
            print "Writing header file: %s" % filePath
284
 
 
285
 
        # Create the containing folder
286
 
        mkdir_p(QtCore.QFile.encodeName(folder).data())
287
 
 
288
 
        # open the header file
289
 
        header = open(filePath, 'w')
290
 
 
291
 
        # get all direct base classes
292
 
        parentClasses = self.getParentClasses(uri)
293
 
 
294
 
        # write protecting ifdefs
295
 
        header_protect = '_%s_%s_H_' % (nsAbbr.toUpper(), className.toUpper())
296
 
        header.write('#ifndef %s\n' % header_protect)
297
 
        header.write('#define %s\n' % header_protect)
298
 
        header.write('\n')
299
 
        
300
 
        # write default includes
301
 
        header.write('#include <QtCore/QVariant>\n')
302
 
        header.write('#include <QtCore/QStringList>\n')
303
 
        header.write('#include <QtCore/QUrl>\n')
304
 
        header.write('#include <QtCore/QDate>\n')
305
 
        header.write('#include <QtCore/QTime>\n')
306
 
        header.write('#include <QtCore/QDateTime>\n')
307
 
        header.write('\n')
308
 
 
309
 
        # all classes need the SimpleResource include
310
 
        header.write('#include <nepomuk/simpleresource.h>\n\n')
311
 
 
312
 
        # write includes for the parent classes
313
 
        parentClassNames = []
314
 
        for parent in parentClasses.keys():
315
 
            header.write('#include "%s/%s.h"\n' % (parentClasses[parent]['ns'], parentClasses[parent]['name'].toLower()))
316
 
            parentClassNames.append("%s::%s" %(parentClasses[parent]['ns'].toUpper(), parentClasses[parent]['name']))
317
 
 
318
 
        # get all base classes which we require due to the virtual base class constructor ordering in C++
319
 
        # We inverse the order to match the virtual inheritance constructor calling order
320
 
        fullParentHierarchyNames = []
321
 
        for parent in self.getFullParentHierarchy(uri, [], []):
322
 
            fullParentHierarchyNames.append("%s::%s" %(parent['ns'].toUpper(), parent['name']))
323
 
 
324
 
        if len(parentClassNames) > 0:
325
 
            header.write('\n')
326
 
 
327
 
        # write the class namespace
328
 
        header.write('namespace Nepomuk {\n')
329
 
        header.write('namespace %s {\n' % nsAbbr.toUpper())
330
 
 
331
 
        # write the class + parent classes
332
 
        # We use virtual inheritance when deriving from SimpleResource since our ontologies
333
 
        # make use of multi-inheritance and without it the compiler would not know which
334
 
        # addProperty and friends to call.
335
 
        # We need to do the same with all parent classes since some classes like
336
 
        # nco:CellPhoneNumber as derived from other classes that have yet another parent
337
 
        # class in common which is not SimpleResource.
338
 
        self.writeComment(header, comment, 0)
339
 
        header.write('class %s' % className)
340
 
        header.write(' : ')
341
 
        header.write(', '.join(['public virtual %s' % (p) for p in parentClassNames]))
342
 
        if len(parentClassNames) == 0:
343
 
            header.write('public virtual Nepomuk::SimpleResource');
344
 
        header.write('\n{\n')
345
 
        header.write('public:\n')
346
 
 
347
 
        # write the default constructor
348
 
        # We directly set the type of the class to the SimpleResource. If the class is a base class
349
 
        # not derived from any other classes then we set the type directly. Otherwise we use the
350
 
        # protected constructor defined below which takes a type as parameter making sure that we
351
 
        # only add one type instead of the whole hierarchy
352
 
        header.write('    %s(const QUrl& uri = QUrl())\n' % className)
353
 
        header.write('      : ')
354
 
        header.write('SimpleResource(uri)')
355
 
        if len(parentClassNames) > 0:
356
 
            header.write(', ')
357
 
            header.write(', '.join([('%s(uri, QUrl::fromEncoded("' + uri.toString().toUtf8().data() + '", QUrl::StrictMode))') % p for p in fullParentHierarchyNames]))
358
 
        header.write(' {\n')
359
 
        if len(parentClassNames) == 0:
360
 
            header.write('        addType(QUrl::fromEncoded("%s", QUrl::StrictMode));\n' % uri.toString())
361
 
        header.write('    }\n\n')
362
 
 
363
 
        # write the copy constructor
364
 
        header.write('    %s(const SimpleResource& res)\n' % className)
365
 
        header.write('      : ')
366
 
        header.write('SimpleResource(res)')
367
 
        if len(parentClassNames) > 0:
368
 
            header.write(', ')
369
 
            header.write(', '.join([('%s(res, QUrl::fromEncoded("' + uri.toString().toUtf8().data() + '", QUrl::StrictMode))') % p for p in fullParentHierarchyNames]))
370
 
        header.write(' {\n')
371
 
        if len(parentClassNames) == 0:
372
 
            header.write('        addType(QUrl::fromEncoded("%s", QUrl::StrictMode));\n' % uri.toString())
373
 
        header.write('    }\n\n')
374
 
 
375
 
        # write the assignment operator
376
 
        header.write('    %s& operator=(const SimpleResource& res) {\n' % className)
377
 
        header.write('        SimpleResource::operator=(res);\n')
378
 
        header.write('        addType(QUrl::fromEncoded("%s", QUrl::StrictMode));\n' % uri.toString())
379
 
        header.write('        return *this;\n')
380
 
        header.write('    }\n\n')
381
 
 
382
 
        # Write getter and setter methods for all properties
383
 
        # This includes the properties that have domain rdfs:Resource on base classes, ie.
384
 
        # those that are not derived from any other class. That way these properties are
385
 
        # accessible from all classes.
386
 
        properties = self.getPropertiesForClass(uri)
387
 
        if len(parentClassNames) == 0:
388
 
            properties.update(self.rdfsResourceProperties)
389
 
 
390
 
        # There could be properties with the same name - in that case we give the methods a prefix
391
 
        for p in properties.keys():
392
 
            name = extractNameFromUri(p)
393
 
            cnt = 0
394
 
            # search for the same name again
395
 
            for op in properties.keys():
396
 
                if extractNameFromUri(op) == name:
397
 
                    cnt+=1
398
 
            if cnt > 1:
399
 
                name = self.getNamespaceAbbreviationForUri(p).toLower() + name[0].toUpper() + name.mid(1)
400
 
            properties[p]['name'] = name;
401
 
            
402
 
        for p in properties.keys():
403
 
            self.writeComment(header, 'Get property %s. %s' % (p.toString(), properties[p]['comment']), 1)
404
 
            self.writeGetter(header, p, properties[p]['name'], properties[p]['range'], properties[p]['cardinality'])
405
 
            header.write('\n')
406
 
            self.writeComment(header, 'Set property %s. %s' % (p.toString(), properties[p]['comment']), 1)
407
 
            self.writeSetter(header, p, properties[p]['name'], properties[p]['range'], properties[p]['cardinality'])
408
 
            header.write('\n')
409
 
            self.writeComment(header, 'Add value to property %s. %s' % (p.toString(), properties[p]['comment']), 1)
410
 
            self.writeAdder(header, p, properties[p]['name'], properties[p]['range'], properties[p]['cardinality'])
411
 
            header.write('\n')
412
 
 
413
 
        # write the protected constructors which avoid adding the whole type hierarchy
414
 
        header.write('protected:\n')
415
 
        header.write('    %s(const QUrl& uri, const QUrl& type)\n' % className)
416
 
        header.write('      : ')
417
 
        header.write('SimpleResource(uri)')
418
 
        if len(parentClassNames) > 0:
419
 
            header.write(', ')
420
 
            header.write(', '.join(['%s(uri, type)' % p for p in fullParentHierarchyNames]))
421
 
        header.write(' {\n')
422
 
        if len(parentClassNames) == 0:
423
 
            header.write('        addType(type);\n')
424
 
        header.write('    }\n')
425
 
 
426
 
        header.write('    %s(const SimpleResource& res, const QUrl& type)\n' % className)
427
 
        header.write('      : ')
428
 
        header.write('SimpleResource(res)')
429
 
        if len(parentClassNames) > 0:
430
 
            header.write(', ')
431
 
            header.write(', '.join(['%s(res, type)' % p for p in fullParentHierarchyNames]))
432
 
        header.write(' {\n')
433
 
        if len(parentClassNames) == 0:
434
 
            header.write('        addType(type);\n')
435
 
        header.write('    }\n')
436
 
 
437
 
        # close the class
438
 
        header.write('};\n')
439
 
 
440
 
        # write the closing parenthesis for the namespaces
441
 
        header.write('}\n}\n')
442
 
 
443
 
        # write the closing preprocessor thingi
444
 
        header.write('\n#endif\n')
445
 
        
446
 
 
447
 
def main():
448
 
    global output_path
449
 
    global verbose
450
 
    
451
 
    usage = "Usage: %prog [options] ontologyfile1 ontologyfile2 ..."
452
 
    optparser = argparse.ArgumentParser(description="Nepomuk SimpleResource code generator. It will generate a hierarchy of simple wrapper classes around Nepomuk::SimpleResource which provide convinience methods to get and set properties of those classes. Each wrapper class will be defined in its own header file and be written to a subdirectory named as the default ontology prefix. Example: the header file for nao:Tag would be written to nao/tag.h and be defined in the namespace Nepomuk::NAO.")
453
 
    optparser.add_argument('--output', '-o', type=str, nargs=1, metavar='PATH', dest='output', help='The destination folder')
454
 
    optparser.add_argument('--quiet', '-q', action="store_false", dest="verbose", default=True, help="don't print status messages to stdout")
455
 
    optparser.add_argument("ontologies", type=str, nargs='+', metavar="ONTOLOGY", help="Ontology files to use")
456
 
 
457
 
    args = optparser.parse_args()
458
 
    if args.output :
459
 
        output_path = args.output[0]
460
 
 
461
 
    verbose = args.verbose
462
 
 
463
 
    if verbose:
464
 
        print 'Generating from ontology files %s' % ','.join(args.ontologies)
465
 
        print 'Writing files to %s.' % output_path
466
 
 
467
 
    # Parse all ontology files
468
 
    ontoParser = OntologyParser()
469
 
    for f in args.ontologies:
470
 
        if verbose:
471
 
            print "Reading ontology '%s'" % f
472
 
        ontoParser.parseFile(f)
473
 
    if verbose:
474
 
        print "All ontologies read. Generating code..."
475
 
 
476
 
    # Get all classes and handle them one by one
477
 
    ontoParser.writeAll()
478
 
 
479
 
if __name__ == "__main__":
480
 
    main()