context: using System;
  using System.Collections.Generic;
  using System.Linq;
  using Nop.Core;
  using Nop.Core.Caching;
  using Nop.Core.Data;
  using Nop.Core.Domain.Catalog;
  using Nop.Services.Events;
  
  namespace Nop.Services.Catalog
  {
      /// <summary>
      /// Specification attribute service
      /// </summary>
      public partial class SpecificationAttributeService : ISpecificationAttributeService
      {
          #region Constants
  
          /// <summary>
          /// Key for caching
          /// </summary>
          /// <remarks>
          /// {0} : product ID
          /// {1} : allow filtering
          /// {2} : show on product page
          /// </remarks>
          private const string PRODUCTSPECIFICATIONATTRIBUTE_ALLBYPRODUCTID_KEY = "Nop.productspecificationattribute.allbyproductid-{0}-{1}-{2}";
          /// <summary>
          /// Key pattern to clear cache
          /// </summary>
          private const string PRODUCTSPECIFICATIONATTRIBUTE_PATTERN_KEY = "Nop.productspecificationattribute.";
          #endregion
  
          #region Fields
          
          private readonly IRepository<SpecificationAttribute> _specificationAttributeRepository;
          private readonly IRepository<SpecificationAttributeOption> _specificationAttributeOptionRepository;
          private readonly IRepository<ProductSpecificationAttribute> _productSpecificationAttributeRepository;
          private readonly ICacheManager _cacheManager;
          private readonly IEventPublisher _eventPublisher;
  
          #endregion
  
          #region Ctor
  
          /// <summary>
          /// Ctor
          /// </summary>
          /// <param name="cacheManager">Cache manager</param>
          /// <param name="specificationAttributeRepository">Specification attribute repository</param>
          /// <param name="specificationAttributeOptionRepository">Specification attribute option repository</param>
          /// <param name="productSpecificationAttributeRepository">Product specification attribute repository</param>
          /// <param name="eventPublisher">Event published</param>
          public SpecificationAttributeService(ICacheManager cacheManager,
              IRepository<SpecificationAttribute> specificationAttributeRepository,
              IRepository<SpecificationAttributeOption> specificationAttributeOptionRepository,
              IRepository<ProductSpecificationAttribute> productSpecificationAttributeRepository,
              IEventPublisher eventPublisher)
          {
              _cacheManager = cacheManager;
              _specificationAttributeRepository = specificationAttributeRepository;
              _specificationAttributeOptionRepository = specificationAttributeOptionRepository;
              _productSpecificationAttributeRepository = productSpecificationAttributeRepository;
              _eventPublisher = eventPublisher;
          }
  
          #endregion
  
          #region Methods
  
          #region Specification attribute
  
          /// <summary>
          /// Gets a specification attribute
          /// </summary>
          /// <param name="specificationAttributeId">The specification attribute identifier</param>
          /// <returns>Specification attribute</returns>
          public virtual SpecificationAttribute GetSpecificationAttributeById(int specificationAttributeId)
          {
              if (specificationAttributeId == 0)
                  return null;
  
              return _specificationAttributeRepository.GetById(specificationAttributeId);
          }
  
          /// <summary>
          /// Gets specification attributes
          /// </summary>
          /// <param name="pageIndex">Page index</param>
          /// <param name="pageSize">Page size</param>
          /// <returns>Specification attributes</returns>
          public virtual IPagedList<SpecificationAttribute> GetSpecificationAttributes(int pageIndex = 0, int pageSize = int.MaxValue)
          {
              var query = from sa in _specificationAttributeRepository.Table
                          orderby sa.DisplayOrder, sa.Id
                          select sa;
              var specificationAttributes = new PagedList<SpecificationAttribute>(query, pageIndex, pageSize);
              return specificationAttributes;
          }
  
          /// <summary>
          /// Deletes a specification attribute
          /// </summary>
          /// <param name="specificationAttribute">The specification attribute</param>
          public virtual void DeleteSpecificationAttribute(SpecificationAttribute specificationAttribute)
          {
              if (specificationAttribute == null)
                  throw new ArgumentNullException("specificationAttribute");
  
              _specificationAttributeRepository.Delete(specificationAttribute);
  
              _cacheManager.RemoveByPattern(PRODUCTSPECIFICATIONATTRIBUTE_PATTERN_KEY);
  
              //event notification
              _eventPublisher.EntityDeleted(specificationAttribute);
          }
  
          /// <summary>
          /// Inserts a specification attribute
          /// </summary>
          /// <param name="specificationAttribute">The specification attribute</param>
          public virtual void InsertSpecificationAttribute(SpecificationAttribute specificationAttribute)
          {
              if (specificationAttribute == null)
                  throw new ArgumentNullException("specificationAttribute");
  
              _specificationAttributeRepository.Insert(specificationAttribute);
  
              _cacheManager.RemoveByPattern(PRODUCTSPECIFICATIONATTRIBUTE_PATTERN_KEY);
  
              //event notification
              _eventPublisher.EntityInserted(specificationAttribute);
          }
  
          /// <summary>
          /// Updates the specification attribute
          /// </summary>
          /// <param name="specificationAttribute">The specification attribute</param>
          public virtual void UpdateSpecificationAttribute(SpecificationAttribute specificationAttribute)
          {
              if (specificationAttribute == null)
                  throw new ArgumentNullException("specificationAttribute");
  
              _specificationAttributeRepository.Update(specificationAttribute);
  
              _cacheManager.RemoveByPattern(PRODUCTSPECIFICATIONATTRIBUTE_PATTERN_KEY);
  
              //event notification
              _eventPublisher.EntityUpdated(specificationAttribute);
          }
  
          #endregion
  
          #region Specification attribute option
  
          /// <summary>
          /// Gets a specification attribute option
          /// </summary>
          /// <param name="specificationAttributeOptionId">The specification attribute option identifier</param>
          /// <returns>Specification attribute option</returns>
          public virtual SpecificationAttributeOption GetSpecificationAttributeOptionById(int specificationAttributeOptionId)
          {
              if (specificationAttributeOptionId == 0)
                  return null;
  
              return _specificationAttributeOptionRepository.GetById(specificationAttributeOptionId);
          }
  
  
          /// <summary>
          /// Get specification attribute options by identifiers
          /// </summary>
          /// <param name="specificationAttributeOptionIds">Identifiers</param>
          /// <returns>Specification attribute options</returns>
          public virtual IList<SpecificationAttributeOption> GetSpecificationAttributeOptionsByIds(int[] specificationAttributeOptionIds)
          {
              if (specificationAttributeOptionIds == null || specificationAttributeOptionIds.Length == 0)
                  return new List<SpecificationAttributeOption>();
  
              var query = from sao in _specificationAttributeOptionRepository.Table
                          where specificationAttributeOptionIds.Contains(sao.Id)
                          select sao;
              var specificationAttributeOptions = query.ToList();
              //sort by passed identifiers
              var sortedSpecificationAttributeOptions = new List<SpecificationAttributeOption>();
              foreach (int id in specificationAttributeOptionIds)
              {
                  var sao = specificationAttributeOptions.Find(x => x.Id == id);
                  if (sao != null)
                      sortedSpecificationAttributeOptions.Add(sao);
              }
              return sortedSpecificationAttributeOptions;
          }
  
          /// <summary>
          /// Gets a specification attribute option by specification attribute id
          /// </summary>
          /// <param name="specificationAttributeId">The specification attribute identifier</param>
          /// <returns>Specification attribute option</returns>
          public virtual IList<SpecificationAttributeOption> GetSpecificationAttributeOptionsBySpecificationAttribute(int specificationAttributeId)
          {
              var query = from sao in _specificationAttributeOptionRepository.Table
                          orderby sao.DisplayOrder
                          where sao.SpecificationAttributeId == specificationAttributeId
                          select sao;
              var specificationAttributeOptions = query.ToList();
              return specificationAttributeOptions;
          }
  
          /// <summary>
          /// Deletes a specification attribute option
          /// </summary>
          /// <param name="specificationAttributeOption">The specification attribute option</param>
          public virtual void DeleteSpecificationAttributeOption(SpecificationAttributeOption specificationAttributeOption)
          {
              if (specificationAttributeOption == null)
                  throw new ArgumentNullException("specificationAttributeOption");
  
              _specificationAttributeOptionRepository.Delete(specificationAttributeOption);
  
              _cacheManager.RemoveByPattern(PRODUCTSPECIFICATIONATTRIBUTE_PATTERN_KEY);
  
              //event notification
              _eventPublisher.EntityDeleted(specificationAttributeOption);
          }
  
          /// <summary>
          /// Inserts a specification attribute option
          /// </summary>
          /// <param name="specificationAttributeOption">The specification attribute option</param>
          public virtual void InsertSpecificationAttributeOption(SpecificationAttributeOption specificationAttributeOption)
          {
              if (specificationAttributeOption == null)
                  throw new ArgumentNullException("specificationAttributeOption");
  
              _specificationAttributeOptionRepository.Insert(specificationAttributeOption);
  
              _cacheManager.RemoveByPattern(PRODUCTSPECIFICATIONATTRIBUTE_PATTERN_KEY);
  
              //event notification
              _eventPublisher.EntityInserted(specificationAttributeOption);
          }
  
          /// <summary>
          /// Updates the specification attribute
          /// </summary>
          /// <param name="specificationAttributeOption">The specification attribute option</param>
          public virtual void UpdateSpecificationAttributeOption(SpecificationAttributeOption specificationAttributeOption)
          {
  
gt:             if (specificationAttributeOption == null)