code: package org.rug.web;
  
  import org.apache.tinkerpop.gremlin.structure.Edge;
  import org.apache.tinkerpop.gremlin.structure.Vertex;
  import org.rug.tracker.ASmellTracker;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Map;
  import java.util.TreeMap;
  
  /**
   * Represents a component (class, package, file, folder, etc.) of the system existing in
   * multiple versions and affected by multiple smells.
   */
  public class Component extends VersionSpanningNode {
  
      private final String name;
      private final String type;
      private final Map<Long, List<Long>> affectedBy;
  
      /**
       * Build the component starting from a component vertex from the condensed graph.
       * @param component the vertex.
       */
      public Component(Vertex component) {
          this.name = component.value(ASmellTracker.NAME);
          this.type = component.value(ASmellTracker.COMPONENT_TYPE);
          this.affectedBy = new TreeMap<>();
          setCharacteristics(component);
          setAffectedBy(component);
      }
  
      /**
       * The identifier of this component.
       * @return a string representing the name of this component.
       */
      public String getName() {
          return name;
      }
  
      /**
       * The type of this component (class, package, file, header, etc.)
       * @return a string representing the type.
       */
      public String getType() {
          return type;
      }
  
      /**
       * A map where the keys are the version indexes and the values are lists of smell ids.
       * @return a map.
       */
      public Map<Long, List<Long>> getAffectedBy() {
          return affectedBy;
      }
  
      private void setAffectedBy(Vertex component){
          var graph = component.graph();
          var affectsEdges = graph.traversal().V(component).inE(ASmellTracker.AFFECTS).toSet();
          for (Edge edge : affectsEdges) {
              affectedBy.compute(edge.value(ASmellTracker.VERSION_INDEX), (k, v) -> {
                  if (v == null){
                      v = new ArrayList<>();
                  }
                  v.add(edge.outVertex().value(ASmellTracker.UNIQUE_SMELL_ID));
                  return v;
              });
          }
      }
  
      private void setCharacteristics(Vertex component){
          var graph = component.graph();
          var hasCharactEdges = graph.traversal().V(component).outE(ASmellTracker.HAS_CHARACTERISTIC).toSet();
          for (Edge edge : hasCharactEdges) {
              long affectedVersion = edge.value(ASmellTracker.VERSION_INDEX);
              spanningVersions.add(affectedVersion);
              characteristics.put(affectedVersion, propertiesToMap(edge.inVertex()));
          }
      }
  }
  