Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-14 09:05:24

0001 // SPDX-License-Identifier: LGPL-3.0-or-later
0002 // Copyright (C) 2025 Wouter Deconinck
0003 //
0004 // Modern datamodel glue for podio >= 1.3
0005 // This file uses podio's built-in TypeList support instead of code generation
0006 //
0007 // **WARNING: This header includes ALL PODIO types (may add significant compile time)**
0008 // Only include this if you need VisitPodioCollection visitor pattern.
0009 //
0010 // For factories using PodioInput/PodioOutput, include JOmniFactory.h which provides
0011 // PodioTypeMap type traits without the overhead of all collection types.
0012 
0013 #pragma once
0014 
0015 #include <stdexcept>
0016 #include <string_view>
0017 #include <unordered_map>
0018 #include <type_traits>
0019 #include <format>
0020 #include <podio/CollectionBase.h>
0021 #include <podio/utilities/TypeHelpers.h>
0022 // Include umbrella headers for TypeList support
0023 // Only files that use the visitor pattern need this full header
0024 // IWYU pragma: begin_exports
0025 #include <edm4hep/edm4hep.h>
0026 #include <edm4eic/edm4eic.h>
0027 // IWYU pragma: end_exports
0028 
0029 // CollectionVisitorMap builds a dispatch table from podio collection type names
0030 // to type-safe visitor functions for a given Visitor type.
0031 //
0032 // The Visitor template parameter is expected to be a callable type (e.g. a
0033 // functor, lambda, or class with operator()) that can be invoked for each
0034 // supported concrete collection type:
0035 //
0036 //   void operator()(const ConcreteCollectionType&);
0037 //
0038 // CollectionVisitorMap is instantiated once per Visitor (see VisitPodioCollection
0039 // below). At construction time it registers all EDM4hep and EDM4eic data and
0040 // link collection types by mapping their static typeName to a function that
0041 // will:
0042 //   1. downcast the generic podio::CollectionBase reference to the concrete
0043 //      collection type, and
0044 //   2. call the Visitor with that concrete collection.
0045 //
0046 // This map is then used by VisitPodioCollection to look up the correct
0047 // handler at runtime based on collection.getTypeName(), providing a
0048 // type-safe implementation of the visitor pattern over podio collections.
0049 template <typename Visitor> class CollectionVisitorMap {
0050 public:
0051   using FunctionType = void (*)(Visitor&, const podio::CollectionBase&);
0052 
0053 private:
0054   std::unordered_map<std::string_view, FunctionType> m_map;
0055 
0056   template <typename CollectionT>
0057   static void visitCollection(Visitor& visitor, const podio::CollectionBase& collection) {
0058     static_assert(std::is_base_of_v<podio::CollectionBase, CollectionT>,
0059                   "CollectionT must be derived from podio::CollectionBase");
0060     visitor(*static_cast<const CollectionT*>(&collection));
0061   }
0062 
0063   template <typename CollectionT> void addToMap() {
0064     m_map[CollectionT::typeName] = &visitCollection<CollectionT>;
0065   }
0066 
0067   template <typename DataT> void addDataTypeToMap() { addToMap<typename DataT::collection_type>(); }
0068 
0069   template <typename... DataTypes>
0070   void addAllDataCollections(podio::utils::TypeList<DataTypes...>) {
0071     (addDataTypeToMap<DataTypes>(), ...);
0072   }
0073 
0074   template <typename... LinkTypes>
0075   void addAllLinkCollections(podio::utils::TypeList<LinkTypes...>) {
0076     (addDataTypeToMap<LinkTypes>(), ...);
0077   }
0078 
0079 public:
0080   CollectionVisitorMap() {
0081     // Add all EDM4hep and EDM4eic data collection types
0082     addAllDataCollections(typename edm4hep::edm4hepDataTypes{});
0083     addAllDataCollections(typename edm4eic::edm4eicDataTypes{});
0084 
0085     // Add all EDM4hep and EDM4eic link collections
0086     addAllLinkCollections(typename edm4hep::edm4hepLinkTypes{});
0087     addAllLinkCollections(typename edm4eic::edm4eicLinkTypes{});
0088   }
0089 
0090   const auto& getMap() const { return m_map; }
0091 };
0092 
0093 // VisitPodioCollection is a visitor adaptor for type-safe processing of podio collections.
0094 //
0095 // This template implements a runtime-dispatch visitor pattern for
0096 // podio::CollectionBase instances. It uses the collection's
0097 // runtime type name together with CollectionVisitorMap to look up the
0098 // concrete collection type and call the provided @p Visitor on it.
0099 //
0100 // template parameter Visitor
0101 //   A type that models a callable taking a const reference to each
0102 //   supported concrete podio collection type. In practice, this means
0103 //   that for every collection type CollectionT registered in
0104 //   CollectionVisitorMap, the following expression must be well-formed:
0105 //
0106 //     visitor(const CollectionT&);
0107 //
0108 //   This can be satisfied either by giving Visitor a suitable
0109 //   operator() overload, or by providing free / member functions
0110 //   that are invocable with const CollectionT&.
0111 //
0112 // Usage:
0113 //   - Construct or obtain a Visitor instance.
0114 //   - Call VisitPodioCollection<Visitor>::operator() with the visitor
0115 //     and a podio::CollectionBase reference. The adaptor will:
0116 //       1. Look up the collection's concrete type by getTypeName().
0117 //       2. Cast the podio::CollectionBase to the matching concrete
0118 //          collection type.
0119 //       3. Invoke the visitor with a const CollectionT& argument.
0120 //
0121 // If the collection type name is not known to the registered EDM4hep or
0122 // EDM4eic datamodels, operator() throws std::runtime_error with a
0123 // descriptive error message.
0124 template <typename Visitor> struct VisitPodioCollection {
0125   void operator()(Visitor& visitor, const podio::CollectionBase& collection) {
0126     // Build the map once (static initialization)
0127     static const CollectionVisitorMap<Visitor> visitorMap;
0128 
0129     auto typeName = collection.getTypeName();
0130     auto it       = visitorMap.getMap().find(typeName);
0131 
0132     if (it != visitorMap.getMap().end()) {
0133       it->second(visitor, collection);
0134     } else {
0135       throw std::runtime_error(std::format(
0136           "Unrecognized podio typename: {}.\n"
0137           "This type was not found in the supported datamodels (EDM4hep, EDM4eic).\n"
0138           "Possible causes:\n"
0139           "  - The type is not defined in EDM4hep or EDM4eic datamodels.\n"
0140           "  - You may be using an incompatible or outdated version of the datamodels.\n"
0141           "  - There may be a typo in the type name.\n"
0142           "Please check your datamodel installation and ensure you are using compatible versions.",
0143           typeName));
0144     }
0145   }
0146 };