class_docstr: Helper class to determine entity name.
docstr: Check if entity has the `name` attribute set.
  
  * If so, no action is taken.
  * If not, and the name can be constructed from other parameters provided, it is created and filled in
      the entity.
  * If both the entity's 'name' attribute is set and the name can be constructed from other parameters
      provided:
      * If they are the same - no action is taken
      * if they are different - an exception is thrown.
  
  :param entity: Entity
  :param entity_id: Entity id
  :param location: Location
  :param project_id: The id of Google Cloud Vision project.
  :return: The same entity or entity with new name
  :raises: AirflowException
code: def get_entity_with_name(
      self,
      entity: Any,
      entity_id: str | None,
      location: str | None,
      project_id: str,
  ) -> Any:
      """
      Check if entity has the `name` attribute set.
  
      * If so, no action is taken.
      * If not, and the name can be constructed from other parameters provided, it is created and filled in
          the entity.
      * If both the entity's 'name' attribute is set and the name can be constructed from other parameters
          provided:
          * If they are the same - no action is taken
          * if they are different - an exception is thrown.
  
      :param entity: Entity
      :param entity_id: Entity id
      :param location: Location
      :param project_id: The id of Google Cloud Vision project.
      :return: The same entity or entity with new name
      :raises: AirflowException
      """
      entity = deepcopy(entity)
      explicit_name = getattr(entity, "name")
      if location and entity_id:
          # Necessary parameters to construct the name are present. Checking for conflict with explicit name
          constructed_name = self.get_path(
              project_id, location, entity_id
          )
          if not explicit_name:
              entity.name = constructed_name
              return entity
  
          if explicit_name != constructed_name:
              raise AirflowException(
                  ERR_DIFF_NAMES.format(
                      label=self.label,
                      explicit_name=explicit_name,
                      constructed_name=constructed_name,
                      id_label=self.id_label,
                  )
              )
  
      # Not enough parameters to construct the name. Trying to use the name from Product / ProductSet.
      if explicit_name:
          return entity
      else:
          raise AirflowException(
              ERR_UNABLE_TO_CREATE.format(
                  label=self.label, id_label=self.id_label
              )
          )
  
imports: from __future__ import annotations
  from copy import deepcopy
  from functools import cached_property
  from typing import TYPE_CHECKING, Any, Callable, Sequence
  from google.api_core.gapic_v1.method import DEFAULT, _MethodDefault
  from google.cloud.vision_v1 import AnnotateImageRequest, Image, ImageAnnotatorClient, Product, ProductSearchClient, ProductSet, ReferenceImage
  from google.protobuf.json_format import MessageToDict
  from airflow.exceptions import AirflowException
  from airflow.providers.google.common.consts import CLIENT_INFO
  from airflow.providers.google.common.hooks.base_google import PROVIDE_PROJECT_ID, GoogleBaseHook
label_desc: Use image node_id 2 for calling the NameDeterminer obj's underlying member method code with example usage: obj.get_entity_with_name(entity, entity_id, location, project_id) and returns: entity, entity