class_docstr: Tracks semantic information for semantic model held in a set of SemanticModelContainers.
  
  This implements both the SemanticModelAccessors protocol, the interface type we use throughout the codebase.
  That interface prevents unwanted calls to methods for adding semantic models to the container.
class_docstr_tok: ["Tracks","semantic","information","for","semantic","model","held","in","a","set","of","SemanticModelContainers",".","This","implements","both","the","SemanticModelAccessors","protocol",",","the","interface","type","we","use","throughout","the","codebase",".","That","interface","prevents","unwanted","calls","to","methods","for","adding","semantic","models","to","the","container","."]
docstr: Add semantic model semantic information, validating consistency with existing semantic models.
code: def _add_semantic_model(self, semantic_model: SemanticModel) -> None:
      """Add semantic model semantic information, validating consistency with existing semantic models."""
      errors = []
  
      if (
          semantic_model.reference
          in self._semantic_model_reference_to_semantic_model
      ):
          errors.append(
              f"Semantic model {semantic_model.reference} already added."
          )
  
      for measure in semantic_model.measures:
          if (
              measure.reference in self._measure_aggs
              and self._measure_aggs[measure.reference] != measure.agg
          ):
              errors.append(
                  f"Conflicting aggregation (agg) for measure {measure.reference}. Currently registered as "
                  f"{self._measure_aggs[measure.reference]} but got {measure.agg}."
              )
  
      if len(errors) > 0:
          raise InvalidSemanticModelError(
              f"Error adding {semantic_model.reference}. Got errors: {errors}"
          )
  
      self._semantic_model_to_aggregation_time_dimensions[
          semantic_model.reference
      ] = ElementGrouper[TimeDimensionReference, MeasureSpec]()
  
      for measure in semantic_model.measures:
          self._measure_aggs[measure.reference] = measure.agg
          self._measure_index[measure.reference].append(semantic_model)
          agg_time_dimension_reference = (
              semantic_model.checked_agg_time_dimension_for_measure(
                  measure.reference
              )
          )
  
          matching_dimensions = tuple(
              dimension
              for dimension in semantic_model.dimensions
              if dimension.type == DimensionType.TIME
              and dimension.time_dimension_reference
              == agg_time_dimension_reference
          )
  
          matching_dimensions_count = len(matching_dimensions)
          if matching_dimensions_count != 1:
              raise RuntimeError(
                  f"Found {matching_dimensions_count} matching dimensions for {agg_time_dimension_reference} "
                  f"in {semantic_model}"
              )
          agg_time_dimension = matching_dimensions[0]
          if (
              agg_time_dimension.type_params is None
              or agg_time_dimension.type_params.time_granularity is None
          ):
              raise RuntimeError(
                  f"Aggregation time dimension does not have a time granularity set: {agg_time_dimension}"
              )
  
          primary_entity = SemanticModelLookup._resolved_primary_entity(
              semantic_model
          )
  
          if primary_entity is None:
              raise RuntimeError(
                  f"The semantic model should have a primary entity since there are dimensions, but it does not. "
                  f"Semantic model is:\n{pformat_big_objects(semantic_model)}"
              )
  
          self._semantic_model_to_aggregation_time_dimensions[
              semantic_model.reference
          ].add_value(
              key=TimeDimensionReference(
                  element_name=agg_time_dimension.name,
              ),
              value=MeasureConverter.convert_to_measure_spec(
                  measure=measure
              ),
          )
          self._measure_agg_time_dimension[
              measure.reference
          ] = TimeDimensionReference(
              element_name=agg_time_dimension.name
          )
  
          if measure.non_additive_dimension:
              non_additive_dimension_spec = NonAdditiveDimensionSpec(
                  name=measure.non_additive_dimension.name,
                  window_choice=measure.non_additive_dimension.window_choice,
                  window_groupings=tuple(
                      measure.non_additive_dimension.window_groupings
                  ),
              )
              self._measure_non_additive_dimension_specs[
                  measure.reference
              ] = non_additive_dimension_spec
      for dim in semantic_model.dimensions:
          self._linkable_reference_index[dim.reference].append(
              semantic_model
          )
          self._dimension_index[dim.reference].append(semantic_model)
          self._dimension_ref_to_spec[
              dim.time_dimension_reference or dim.reference
          ] = (
              TimeDimensionSpec.from_name(dim.name)
              if dim.type is DimensionType.TIME
              else DimensionSpec.from_name(dim.name)
          )
  
      for entity in semantic_model.entities:
          self._entity_ref_to_entity[entity.reference] = entity.name
          self._entity_index[entity.name].append(semantic_model)
          self._linkable_reference_index[entity.reference].append(
              semantic_model
          )
          self._entity_ref_to_spec[
              entity.reference
          ] = EntitySpec.from_name(entity.name)
  
      self._semantic_model_reference_to_semantic_model[
          semantic_model.reference
      ] = semantic_model
  
imports: from __future__ import annotations
  import logging
  from collections import defaultdict
  from copy import deepcopy
  from typing import Dict, List, Optional, Sequence, Set
  from dbt_semantic_interfaces.pretty_print import pformat_big_objects
  from dbt_semantic_interfaces.protocols.dimension import Dimension
  from dbt_semantic_interfaces.protocols.entity import Entity
  from dbt_semantic_interfaces.protocols.measure import Measure
  from dbt_semantic_interfaces.protocols.semantic_manifest import SemanticManifest
  from dbt_semantic_interfaces.protocols.semantic_model import SemanticModel
  from dbt_semantic_interfaces.references import DimensionReference, EntityReference, LinkableElementReference, MeasureReference, SemanticModelElementReference, SemanticModelReference, TimeDimensionReference
  from dbt_semantic_interfaces.type_enums import DimensionType, EntityType
  from dbt_semantic_interfaces.type_enums.aggregation_type import AggregationType
  from typing_extensions import override
  from metricflow.errors.errors import InvalidSemanticModelError
  from metricflow.model.semantics.element_group import ElementGrouper
  from metricflow.model.spec_converters import MeasureConverter
  from metricflow.protocols.semantics import SemanticModelAccessor
  from metricflow.specs.specs import DimensionSpec, EntitySpec, LinkableInstanceSpec, MeasureSpec, NonAdditiveDimensionSpec, TimeDimensionSpec
label_desc: Use image node_id 15 for calling the SemanticModelLookup obj's underlying member method code with example usage: obj._add_semantic_model(semantic_model) without return types