docs: def get_resource_component_and_children(
          self, resource_id, resource_type="collection", level=1, sort_data={}, **kwargs
      ):
          """
          Fetch detailed metadata for the specified resource_id and all of its children.
  
          :param long resource_id: The resource for which to fetch metadata.
          :param string resource_type: The level of description of the record.
          :param int recurse_max_level: The maximum depth level to fetch when fetching children.
              Default is to fetch all of the resource's children, descending as deeply as necessary.
              Pass 1 to fetch no children.
          :param string search_pattern: If specified, limits fetched children to those whose titles or IDs match the provided query.
              See ArchivistsToolkitClient.find_collection_ids for documentation of the query format.
  
          :return: A dict containing detailed metadata about both the requested resource and its children.
              The dict follows this format:
          {
            'id': '31',
            'type': 'resource',
            'sortPosition': '1',
            'identifier': 'PR01',
            'title': 'Parent',
            'levelOfDescription': 'collection',
            'dates': '1880-1889',
            'date_expression': '1880 to 1889',
            'notes': [
              'type': 'odd',
              'content': 'This is a note',
            ],
            'children': [{
              'id': '23',
              'type': 'resource_component',
              'sortPosition': '2',
              'identifier': 'CH01',
              'title': 'Child A',
              'levelOfDescription': 'Sousfonds',
              'dates': '1880-1888',
              'date_expression': '1880 to 1888',
              'notes': [],
              'children': [{
                'id': '24',
                'type': 'resource_component',
                'sortPosition': '3',
                'identifier': 'GR01',
                'title': 'Grandchild A',
                'levelOfDescription': 'Item',
                'dates': '1880-1888',
                'date_expression': '1880 to 1888',
                'notes': [],
                'children': False
              },
              {
                'id': '25',
                'type': 'resource_component',
                'sortPosition': '4',
                'identifier': 'GR02',
                'title': 'Grandchild B',
                'levelOfDescription': 'Item',
                'notes': [],
                'children': False
              }]
            },
            {
              'id': '26',
              'type': 'resource_component',
              'sortPosition': '5',
              'identifier': 'CH02',
              'title': 'Child B',
              'levelOfDescription': 'Sousfonds',
              'dates': '1889',
              'date_expression': '1889',
              'notes': [],
              'children': False
            }]
          }
          :rtype list:
          """
          # we pass the sort position as a dict so it passes by reference and we
          # can use it to share state during recursion
  
          recurse_max_level = kwargs.get("recurse_max_level", False)
          query = kwargs.get("search_pattern", "")
  
          # intialize sort position if this is the beginning of recursion
          if level == 1:
              sort_data["position"] = 0
  
          sort_data["position"] = sort_data["position"] + 1
  
          resource_data = {}
  
          cursor = self.db.cursor()
  
          if resource_type == "collection":
              cursor.execute(
                  "SELECT title, dateExpression, resourceIdentifier1, resourceLevel FROM Resources WHERE resourceid=%s",
                  (resource_id),
              )
  
              for row in cursor.fetchall():
                  resource_data["id"] = resource_id
                  resource_data["type"] = "resource"
                  resource_data["sortPosition"] = sort_data["position"]
                  resource_data["title"] = row[0]
                  # TODO reformat dates from the separate date fields, like ArchivesSpaceClient?
                  resource_data["dates"] = row[1]
                  resource_data["date_expression"] = row[1]
                  resource_data["identifier"] = row[2]
                  resource_data["levelOfDescription"] = row[3]
          else:
              cursor.execute(
                  "SELECT title, dateExpression, persistentID, resourceLevel FROM ResourcesComponents WHERE resourceComponentId=%s",
                  (resource_id),
              )
  
              for row in cursor.fetchall():
                  resource_data["id"] = resource_id
                  resource_data["type"] = "resource_component"
                  resource_data["sortPosition"] = sort_data["position"]
                  resource_data["title"] = row[0]
                  resource_data["dates"] = row[1]
                  resource_data["date_expression"] = row[1]
                  resource_data["identifier"] = row[2]
                  resource_data["levelOfDescription"] = row[3]
  
          # fetch children if we haven't reached the maximum recursion level
          if resource_type == "collection":
              if query == "":
                  cursor.execute(
                      "SELECT resourceComponentId FROM ResourcesComponents WHERE parentResourceComponentId IS NULL AND resourceId=%s ORDER BY FIND_IN_SET(resourceLevel, 'subseries,file'), title ASC",
                      (resource_id),
                  )
              else:
                  cursor.execute(
                      "SELECT resourceComponentId FROM ResourcesComponents WHERE parentResourceComponentId IS NULL AND resourceId=%s AND (title LIKE %s OR persistentID LIKE %s) ORDER BY FIND_IN_SET(resourceLevel, 'subseries,file'), title ASC",
                      (resource_id, "%" + query + "%", "%" + query + "%"),
                  )
          else:
              if query == "":
                  cursor.execute(
                      "SELECT resourceComponentId FROM ResourcesComponents WHERE parentResourceComponentId=%s ORDER BY FIND_IN_SET(resourceLevel, 'subseries,file'), title ASC",
                      (resource_id),
                  )
              else:
                  cursor.execute(
                      "SELECT resourceComponentId FROM ResourcesComponents WHERE parentResourceComponentId=%s AND (title LIKE %s OR persistentID LIKE %s) ORDER BY FIND_IN_SET(resourceLevel, 'subseries,file'), title ASC",
                      (resource_id, "%" + query + "%", "%" + query + "%"),
                  )
  
          rows = cursor.fetchall()
  
          if (not recurse_max_level) or level < recurse_max_level:
              if len(rows):
                  resource_data["children"] = []
                  resource_data["has_children"] = True
  
                  for row in rows:
                      resource_data["children"].append(
                          self.get_resource_component_and_children(
                              row[0], "description", level + 1, sort_data
                          )
                      )
          else:
              if len(rows):
                  resource_data["children"] = []
                  resource_data["has_children"] = True
              else:
                  resource_data["children"] = False
                  resource_data["has_children"] = False
  
          # TODO: implement fetching notes
          resource_data["notes"] = []
  
          return resource_data