6 CreateClassesForFolder.py
8 Python script that creates C++ .h/.cxx files that contain the container and object class
9 representing the structure of a database folder.
18 from CLIDComps.clidGenerator
import clidGenerator
19 from PyCool
import cool,coral
21 _dbSvc = cool.DatabaseSvcFactory.databaseService()
22 _cliddb = clidGenerator(
"")
24 _container_header =
"""// -*- C++ -*-
25 #ifndef TRIGT1CALOCALIBCONDITIONS_${CONTAINERNAME}_H
26 #define TRIGT1CALOCALIBCONDITIONS_${CONTAINERNAME}_H
31 #include "AthenaKernel/CLASS_DEF.h"
32 #include "GaudiKernel/DataObject.h"
33 #include "TrigT1CaloCalibConditions/AbstractL1CaloPersistentCondition.h"
34 #include "TrigT1CaloCalibConditions/L1CaloCoolChannelId.h"
36 class CondAttrListCollection;
40 * Container of ${ObjectName} objects. Automatically created using:
44 class ${ContainerName} : public DataObject, virtual public AbstractL1CaloPersistentCondition
47 enum eAttrSpecification { ${EnumAttrSpecification} };
50 ${ContainerName}(const std::string& folderKey);
51 virtual ~${ContainerName}() {}
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(); }
62 const ${ObjectName}* ${folderName}(unsigned int channelId) const;
63 const ${ObjectName}* ${folderName}(const L1CaloCoolChannelId& channelId) const {
64 return ${folderName}(channelId.id());
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(); }
72 void add${FolderName}(const ${ObjectName}& ${folderName});
75 std::vector<${ObjectName}> m_${folderName}s;
76 std::string m_coolFolderKey = "${FullFolderPath}";
81 #endif // TRIGT1CALOCALIBCONDITIONS_${CONTAINERNAME}_H
84 _container_src =
"""#include "TrigT1CaloCalibConditions/${ContainerName}.h"
89 #include "CoralBase/AttributeListSpecification.h"
90 #include "AthenaPoolUtilities/CondAttrListCollection.h"
91 #include "AthenaPoolUtilities/AthenaAttributeList.h"
93 #include "TrigT1CaloCalibConditions/${ObjectName}.h"
95 ${ContainerName}::${ContainerName}()
96 : AbstractL1CaloPersistentCondition("CondAttrListCollection")
98 ${DefineSpecificationList}
101 ${ContainerName}::${ContainerName}(const std::string& folderKey)
102 : ${ContainerName}() // delegating constructor
104 m_coolFolderKey = folderKey;
108 DataObject* ${ContainerName}::makePersistent() const
110 using std::make_unique;
112 if(m_coolFolderKey.empty()) return nullptr;
114 auto* attrSpecification = this->createAttributeListSpecification();
115 if(!attrSpecification || !attrSpecification->size()) return nullptr;
117 auto attrListCollection = make_unique<CondAttrListCollection>(true);
118 for(const auto& item : m_${folderName}s) {
119 AthenaAttributeList attrList(*attrSpecification);
120 ${AddSpecificationList}
122 attrListCollection->add(item.channelId(), attrList);
124 return static_cast<DataObject*>(attrListCollection.release());
127 void ${ContainerName}::makeTransient(const std::map<std::string, const CondAttrListCollection*> condAttrListCollectionMap)
131 auto it = condAttrListCollectionMap.find(m_coolFolderKey);
132 if(it == std::end(condAttrListCollectionMap)) return;
134 auto attrListCollection = it->second;
135 for(const auto& item : *attrListCollection) {
136 auto chanNum = item.first;
137 const auto& attrList = item.second;
139 ${ReadSpecificationList}
141 add${FolderName}(${ObjectName}(chanNum, ${AttrList}));
145 const ${ObjectName}* ${ContainerName}::${folderName}(unsigned int channelId) const
147 auto it = std::lower_bound(std::begin(m_${folderName}s),
148 std::end(m_${folderName}s),
150 [](const ${ObjectName}& el, unsigned int val) -> bool {
151 return el.channelId() < val;
153 if(it == std::end(m_${folderName}s)) return nullptr;
157 void ${ContainerName}::add${FolderName}(const ${ObjectName}& ${folderName})
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;
170 _object_header =
"""// -*- C++ -*-
171 #ifndef TRIGT1CALOCALIBCONDITIONS_${OBJECTNAME}_H
172 #define TRIGT1CALOCALIBCONDITIONS_${OBJECTNAME}_H
175 * Folder <-> Object mapping for ${FullFolderPath} .
176 * Automatically created using:
184 ${ObjectName}(unsigned int channelId, ${AttrTypeNameList});
186 unsigned int channelId() const { return m_channelId; }
189 void setChannelId(unsigned int channelId) { m_channelId = channelId; }
193 unsigned int m_channelId = 0;
197 #endif // TRIGT1CALOCALIBCONDITIONS_${OBJECTNAME}_H
200 _object_src =
"""#include "TrigT1CaloCalibConditions/${ObjectName}.h"
202 ${ObjectName}::${ObjectName}(unsigned int channelId, ${AttrTypeNameList})
203 : m_channelId(channelId)
204 ${AttrConstructorList}
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')
221 'UInt16':
'unsigned short',
222 'UInt32':
'unsigned int',
223 'UInt63':
'unsigned long long',
233 return '{0}{1}'.
format(identifier[0].lower(), identifier[1:])
236 _l =
' attrList[specificationName(e{AttrName})].setValue(item.{attrName}());'
238 for name
in nameList:
239 result.append(_l.format(AttrName=name, attrName=
_toCamelCase(name)))
240 return '\n'.
join(result)
243 _l =
' this->addSpecification(e{AttrName}, "{AttrName}", "{attrType}");'
245 for (n, t)
in nameTypeList:
246 result.append(_l.format(AttrName=n, attrType=
_mapToCpp(t)))
247 return '\n'.
join(result)
250 _l =
' auto {attrName} = attrList[specificationName(e{AttrName})].data<{attrType}>();'
252 for (n, t)
in nameTypeList:
254 return '\n'.
join(result)
257 _l =
' {attrType} {attrName}() const {{ return m_{attrName}; }}'
259 for (n, t)
in nameTypeList:
261 return '\n'.
join(result)
264 _l =
' void set{AttrName}({attrType} {attrName}) {{ m_{attrName} = {attrName}; }}'
266 for (n, t)
in nameTypeList:
268 return '\n'.
join(result)
271 _l =
' {attrType} m_{attrName} = 0;'
273 for (n, t)
in nameTypeList:
275 return '\n'.
join(result)
278 _l =
' , m_{attrName}({attrName})'
282 return '\n'.
join(result)
286 f.write(string.Template(template).
substitute(mapping))
290 """ Does the actual work ... """
291 folderName = folder.fullPath().
split(
'/')[-1]
292 attrNames = [ps.name()
for ps
in folder.payloadSpecification()]
294 attrNames =
filter(
lambda n: n
in attrIncludeList, attrNames)
295 elif attrExcludeList:
296 attrNames =
filter(
lambda n: n
not in attrExcludeList, attrNames)
298 attrTypes = [ps.storageType().
name()
for ps
in folder.payloadSpecification() \
299 if ps.name()
in attrNames]
300 attrNameTypes = zip(attrNames, attrTypes)
302 if not containerName:
303 containerName =
'L1Calo{0}Container'.
format(folderName)
305 objectName =
'L1Calo{0}'.
format(folderName)
309 mapping[
'CommandLine'] =
' '.
join(sys.argv)
310 mapping[
'ContainerName'] = containerName
311 mapping[
'CONTAINERNAME'] = containerName.upper()
312 mapping[
'FolderName'] = 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))
324 mapping[
'AttrList'] =
', '.
join(map(_toCamelCase, attrNames))
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()
348 'cont' : containerName,
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)
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)
362 print ' {cont}::const_iterator {cont}ConstInterator;'.
format(**mapping)
366 parser = argparse.ArgumentParser(description=
'Create C++ classes that represent COOL database folders')
368 args = parser.parse_args()
370 if args.include
and args.exclude:
371 raise RuntimeError(
"Options --include and --exclude are mutually exclusive.")
373 db = _dbSvc.openDatabase(args.db)
374 folder = db.getFolder(args.folder)
377 args.exclude.split(
',')
if args.exclude
else None,
378 args.include.split(
',')
if args.include
else None,
379 args.containerName, args.objectName)
381 if __name__ ==
"__main__":