ATLAS Offline Software
Loading...
Searching...
No Matches
CreateClassesForFolder.py
Go to the documentation of this file.
1#!/usr/bin/env python
2
3# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
4
5__doc__ = """
6CreateClassesForFolder.py
7
8Python script that creates C++ .h/.cxx files that contain the container and object class
9representing the structure of a database folder.
10"""
11
12import argparse
13import os.path
14import string
15import sys
16import uuid
17
18from CLIDComps.clidGenerator import clidGenerator
19from PyCool import cool,coral
20
21_dbSvc = cool.DatabaseSvcFactory.databaseService()
22_cliddb = clidGenerator("")
23
24_container_header = """// -*- C++ -*-
25#ifndef TRIGT1CALOCALIBCONDITIONS_${CONTAINERNAME}_H
26#define TRIGT1CALOCALIBCONDITIONS_${CONTAINERNAME}_H
27
28#include <map>
29#include <string>
30#include <vector>
31#include "AthenaKernel/CLASS_DEF.h"
32#include "GaudiKernel/DataObject.h"
33#include "TrigT1CaloCalibConditions/AbstractL1CaloPersistentCondition.h"
34#include "TrigT1CaloCalibConditions/L1CaloCoolChannelId.h"
35
36class CondAttrListCollection;
37class ${ObjectName};
38
39/***
40* Container of ${ObjectName} objects. Automatically created using:
41*
42* ${CommandLine}
43*/
44class ${ContainerName} : public DataObject, virtual public AbstractL1CaloPersistentCondition
45{
46private:
47 enum eAttrSpecification { ${EnumAttrSpecification} };
48public:
49 ${ContainerName}();
50 ${ContainerName}(const std::string& folderKey);
51 virtual ~${ContainerName}() {}
52
53 // interface of AbstractL1CaloPersistentCondition
54 using AbstractL1CaloPersistentCondition::makeTransient;
55 virtual void makeTransient(const std::map<std::string, const CondAttrListCollection*>);
56 virtual DataObject* makePersistent() const;
57 virtual std::vector<std::string> coolInputKeys() const { return {m_coolFolderKey}; }
58 virtual std::string coolOutputKey() const { return m_coolFolderKey; }
59 virtual void clear() { m_${folderName}s.clear(); }
60
61 // getters
62 const ${ObjectName}* ${folderName}(unsigned int channelId) const;
63 const ${ObjectName}* ${folderName}(const L1CaloCoolChannelId& channelId) const {
64 return ${folderName}(channelId.id());
65 }
66
67 using const_iterator = std::vector<${ObjectName}>::const_iterator;
68 const_iterator begin() const { return m_${folderName}s.begin(); }
69 const_iterator end() const { return m_${folderName}s.end(); }
70
71 // setters
72 void add${FolderName}(const ${ObjectName}& ${folderName});
73
74private:
75 std::vector<${ObjectName}> m_${folderName}s;
76 std::string m_coolFolderKey = "${FullFolderPath}";
77};
78
79${ClassDefMacro}
80
81#endif // TRIGT1CALOCALIBCONDITIONS_${CONTAINERNAME}_H
82"""
83
84_container_src = """#include "TrigT1CaloCalibConditions/${ContainerName}.h"
85
86#include <algorithm>
87#include <memory>
88
89#include "CoralBase/AttributeListSpecification.h"
90#include "AthenaPoolUtilities/CondAttrListCollection.h"
91#include "AthenaPoolUtilities/AthenaAttributeList.h"
92
93#include "TrigT1CaloCalibConditions/${ObjectName}.h"
94
95${ContainerName}::${ContainerName}()
96 : AbstractL1CaloPersistentCondition("CondAttrListCollection")
97{
98${DefineSpecificationList}
99}
100
101${ContainerName}::${ContainerName}(const std::string& folderKey)
102 : ${ContainerName}() // delegating constructor
103{
104 m_coolFolderKey = folderKey;
105}
106
107
108DataObject* ${ContainerName}::makePersistent() const
109{
110 using std::make_unique;
111
112 if(m_coolFolderKey.empty()) return nullptr;
113
114 auto* attrSpecification = this->createAttributeListSpecification();
115 if(!attrSpecification || !attrSpecification->size()) return nullptr;
116
117 auto attrListCollection = make_unique<CondAttrListCollection>(true);
118 for(const auto& item : m_${folderName}s) {
119 AthenaAttributeList attrList(*attrSpecification);
120${AddSpecificationList}
121
122 attrListCollection->add(item.channelId(), attrList);
123 }
124 return static_cast<DataObject*>(attrListCollection.release());
125}
126
127void ${ContainerName}::makeTransient(const std::map<std::string, const CondAttrListCollection*> condAttrListCollectionMap)
128{
129 clear();
130
131 auto it = condAttrListCollectionMap.find(m_coolFolderKey);
132 if(it == std::end(condAttrListCollectionMap)) return;
133
134 auto attrListCollection = it->second;
135 for(const auto& item : *attrListCollection) {
136 auto chanNum = item.first;
137 const auto& attrList = item.second;
138
139${ReadSpecificationList}
140
141 add${FolderName}(${ObjectName}(chanNum, ${AttrList}));
142 }
143}
144
145const ${ObjectName}* ${ContainerName}::${folderName}(unsigned int channelId) const
146{
147 auto it = std::lower_bound(std::begin(m_${folderName}s),
148 std::end(m_${folderName}s),
149 channelId,
150 [](const ${ObjectName}& el, unsigned int val) -> bool {
151 return el.channelId() < val;
152 });
153 if(it == std::end(m_${folderName}s)) return nullptr;
154 return &(*it);
155}
156
157void ${ContainerName}::add${FolderName}(const ${ObjectName}& ${folderName})
158{
159 // insert into the correct position mainting the sorted vector
160 m_${folderName}s.insert(std::lower_bound(std::begin(m_${folderName}s),
161 std::end(m_${folderName}s),
162 ${folderName}.channelId(),
163 [](const ${ObjectName}& el, unsigned int va) -> bool {
164 return el.channelId() < va;
165 }),
166 ${folderName});
167}
168"""
169
170_object_header = """// -*- C++ -*-
171#ifndef TRIGT1CALOCALIBCONDITIONS_${OBJECTNAME}_H
172#define TRIGT1CALOCALIBCONDITIONS_${OBJECTNAME}_H
173
174/**
175 * Folder <-> Object mapping for ${FullFolderPath} .
176 * Automatically created using:
177 *
178 * ${CommandLine}
179 */
180class ${ObjectName}
181{
182public:
183 ${ObjectName}() {}
184 ${ObjectName}(unsigned int channelId, ${AttrTypeNameList});
185
186 unsigned int channelId() const { return m_channelId; }
187${GetterList}
188
189 void setChannelId(unsigned int channelId) { m_channelId = channelId; }
190${SetterList}
191
192private:
193 unsigned int m_channelId = 0;
194${AttrDefinitions}
195};
196
197#endif // TRIGT1CALOCALIBCONDITIONS_${OBJECTNAME}_H
198"""
199
200_object_src = """#include "TrigT1CaloCalibConditions/${ObjectName}.h"
201
202${ObjectName}::${ObjectName}(unsigned int channelId, ${AttrTypeNameList})
203 : m_channelId(channelId)
204${AttrConstructorList}
205{
206}
207"""
208
209def add_args(parser):
210 """ Add arguments to the ArgumentParser @parser. """
211 parser.add_argument('folder', help='Folder which the class should represent')
212 parser.add_argument('--include', help='Comma separated list of attributes to include')
213 parser.add_argument('--exclude', help='Comma separated list of attributes to exclude')
214 parser.add_argument('--objectName', help='Name of object class')
215 parser.add_argument('--containerName', help='Name of container class')
216 parser.add_argument('--db', help='Connection string of the database',
217 default='COOLONL_TRIGGER/CONDBR2')
218
220 _m = {
221 'UInt16': 'unsigned short',
222 'UInt32': 'unsigned int',
223 'UInt63': 'unsigned long long',
224 'Int16' : 'short',
225 'Int32' : 'int',
226 'Double': 'double',
227 'Blob64k': 'char*',
228 'String255': 'char*'
229 }
230 return _m[t]
231
232def _toCamelCase(identifier):
233 return '{0}{1}'.format(identifier[0].lower(), identifier[1:])
234
236 _l = ' attrList[specificationName(e{AttrName})].setValue(item.{attrName}());'
237 result = []
238 for name in nameList:
239 result.append(_l.format(AttrName=name, attrName=_toCamelCase(name)))
240 return '\n'.join(result)
241
243 _l = ' this->addSpecification(e{AttrName}, "{AttrName}", "{attrType}");'
244 result = []
245 for (n, t) in nameTypeList:
246 result.append(_l.format(AttrName=n, attrType=_mapToCpp(t)))
247 return '\n'.join(result)
248
250 _l = ' auto {attrName} = attrList[specificationName(e{AttrName})].data<{attrType}>();'
251 result = []
252 for (n, t) in nameTypeList:
253 result.append(_l.format(AttrName=n, attrName=_toCamelCase(n), attrType=_mapToCpp(t)))
254 return '\n'.join(result)
255
256def _createGetterList(nameTypeList):
257 _l = ' {attrType} {attrName}() const {{ return m_{attrName}; }}'
258 result = []
259 for (n, t) in nameTypeList:
260 result.append(_l.format(attrName=_toCamelCase(n), attrType=_mapToCpp(t)))
261 return '\n'.join(result)
262
263def _createSetterList(nameTypeList):
264 _l = ' void set{AttrName}({attrType} {attrName}) {{ m_{attrName} = {attrName}; }}'
265 result = []
266 for (n, t) in nameTypeList:
267 result.append(_l.format(AttrName=n, attrName=_toCamelCase(n), attrType=_mapToCpp(t)))
268 return '\n'.join(result)
269
270def _createAttrDefinitions(nameTypeList):
271 _l = ' {attrType} m_{attrName} = 0;'
272 result = []
273 for (n, t) in nameTypeList:
274 result.append(_l.format(attrName=_toCamelCase(n), attrType=_mapToCpp(t)))
275 return '\n'.join(result)
276
278 _l = ' , m_{attrName}({attrName})'
279 result = []
280 for n in nameList:
281 result.append(_l.format(attrName=_toCamelCase(n)))
282 return '\n'.join(result)
283
284def _writeToFile(fname, template, mapping):
285 f = open(fname, 'w')
286 f.write(string.Template(template).substitute(mapping))
287 f.close()
288
289def create_classes_from_folder(folder, attrExcludeList, attrIncludeList, containerName, objectName):
290 """ Does the actual work ... """
291 folderName = folder.fullPath().split('/')[-1]
292 attrNames = [ps.name() for ps in folder.payloadSpecification()]
293 if attrIncludeList:
294 attrNames = filter(lambda n: n in attrIncludeList, attrNames)
295 elif attrExcludeList:
296 attrNames = filter(lambda n: n not in attrExcludeList, attrNames)
297
298 attrTypes = [ps.storageType().name() for ps in folder.payloadSpecification() \
299 if ps.name() in attrNames]
300 attrNameTypes = zip(attrNames, attrTypes)
301
302 if not containerName:
303 containerName = 'L1Calo{0}Container'.format(folderName)
304 if not objectName:
305 objectName = 'L1Calo{0}'.format(folderName)
306
307 # prepare the replacements for the container class
308 mapping = {}
309 mapping['CommandLine'] = ' '.join(sys.argv)
310 mapping['ContainerName'] = containerName
311 mapping['CONTAINERNAME'] = containerName.upper()
312 mapping['FolderName'] = folderName
313 mapping['folderName'] = _toCamelCase(folderName)
314 mapping['ObjectName'] = objectName
315 mapping['EnumAttrSpecification'] = ', '.join(['e{0}'.format(n) for n in attrNames])
316 mapping['FullFolderPath'] = folder.fullPath()
317 mapping['ClassDefMacro'] = \
318 'CLASS_DEF( {0}, {1}, 1 )'.format(containerName,
319 _cliddb.genClidFromName(containerName))
320
321 mapping['DefineSpecificationList'] = _createDefineSpecificationList(attrNameTypes)
322 mapping['AddSpecificationList'] = _createAddSpecificationList(attrNames)
323 mapping['ReadSpecificationList'] = _createReadSpecificationList(attrNameTypes)
324 mapping['AttrList'] = ', '.join(map(_toCamelCase, attrNames))
325
326 # write the files
327 _writeToFile('{0}.h'.format(containerName), _container_header, mapping)
328 _writeToFile('{0}.cxx'.format(containerName), _container_src, mapping)
329
330 # prepare the replacements for the object class
331 for not_needed in ('ContainerName', 'CONTAINERNAME', 'FolderName', 'folderName',
332 'EnumAttrSpecification', 'ClassDefMacro', 'DefineSpecificationList',
333 'AddSpecificationList', 'ReadSpecificationList', 'AttrList'):
334 del mapping[not_needed]
335 mapping['OBJECTNAME'] = objectName.upper()
336 mapping['AttrTypeNameList'] = ', '.join(['{0} {1}'.format(_mapToCpp(t), _toCamelCase(n)) for (n,t) in attrNameTypes])
337 mapping['GetterList'] = _createGetterList(attrNameTypes)
338 mapping['SetterList'] = _createSetterList(attrNameTypes)
339 mapping['AttrDefinitions'] = _createAttrDefinitions(attrNameTypes)
340 mapping['AttrConstructorList'] = _createAttrConstructorList(attrNames)
341
342 # write the files
343 _writeToFile('{0}.h'.format(objectName), _object_header, mapping)
344 _writeToFile('{0}.cxx'.format(objectName), _object_src, mapping)
345
346 # redefine mapping for slection.xml / *PACKAGE*Dict.h
347 mapping = {
348 'cont' : containerName,
349 'obj' : objectName,
350 'id' : str(uuid.uuid4()).upper()
351 }
352 print
353 print '[I] Add the following to the selection.xml file:'
354 print ' <class name="{cont}" id="{id}" />'.format(**mapping)
355 print ' <class name="{cont}::const_iterator" />'.format(**mapping)
356 print ' <class name="{obj}" />'.format(**mapping)
357 print
358 print '[I] Add the following to the TrigT1CaloCalibConditionsDict.h file:'
359 print '#include "TrigT1CaloCalibConditions/{cont}.h"'.format(**mapping)
360 print '#include "TrigT1CaloCalibConditions/{obj}.h"'.format(**mapping)
361 print
362 print ' {cont}::const_iterator {cont}ConstInterator;'.format(**mapping)
363
364def main():
365 """ Entry point """
366 parser = argparse.ArgumentParser(description='Create C++ classes that represent COOL database folders')
367 add_args(parser)
368 args = parser.parse_args()
369
370 if args.include and args.exclude:
371 raise RuntimeError("Options --include and --exclude are mutually exclusive.")
372
373 db = _dbSvc.openDatabase(args.db)
374 folder = db.getFolder(args.folder)
375
377 args.exclude.split(',') if args.exclude else None,
378 args.include.split(',') if args.include else None,
379 args.containerName, args.objectName)
380
381if __name__ == "__main__":
382 main();
int upper(int c)
STL class.
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
_writeToFile(fname, template, mapping)
create_classes_from_folder(folder, attrExcludeList, attrIncludeList, containerName, objectName)
_createDefineSpecificationList(nameTypeList)