code: package org.rug.data.characteristics;
  
  import org.rug.data.characteristics.smells.*;
  import org.rug.data.smells.ArchitecturalSmell;
  
  import java.util.Collections;
  import java.util.LinkedHashSet;
  import java.util.Set;
  
  /**
   * Represents a set of stateless characteristics that are calculated by a certain type of smell.
   * Every instance of a characteristic set will be instantiated only once.
   */
  public abstract class SmellCharacteristicsSet {
  
      private final Set<ISmellCharacteristic> characteristics;
  
      public SmellCharacteristicsSet(){
          Set<ISmellCharacteristic> characteristics = new LinkedHashSet<>();
          addSmellGenericCharacteristics(characteristics);
          addSmellSpecificCharacteristics(characteristics);
          this.characteristics = Collections.unmodifiableSet(characteristics);
      }
  
  
      /**
       * Returns the sets of characteristics.
       * @return an unmodifiable set of characteristics.
       */
      public final Set<ISmellCharacteristic> getCharacteristicSet(){
          return characteristics;
      }
  
      /**
       * Instantiates a new set of characteristics that can be used to save their calculations.
       * @param characteristics the set to add the characteristics to
       */
      protected abstract void addSmellSpecificCharacteristics(Set<ISmellCharacteristic> characteristics);
  
      /**
       * Instantiates the smell-generic characteristics and adds them to the given set
       * @param characteristics the set to add the characteristics to.
       */
      private void addSmellGenericCharacteristics(Set<ISmellCharacteristic> characteristics){
          characteristics.add(new Size());
          characteristics.add(new AverageNumOfChanges());
          characteristics.add(new OverlapRatio());
          characteristics.add(new PageRank());
          characteristics.add(new PageRank("pageRankAvrg", x -> x.average().orElse(0)));
          characteristics.add(new NumberOfEdges());
          characteristics.add(new AffectedComponentsType());
          characteristics.add(new CentreComponent());
      }
  }
  