title: Open / Closed Principle & Single Responsibilty -- Graphs
body: <p>I am coding a Graph exploration program and have hit a bit of a stumbling block.</p>
  
  <p>My graph is made up of <code>Vertex</code> and <code>NetworkLink</code> objects, and can be obatined by querying a <code>GeographyModel</code> object.</p>
  
  <p>The idea is <code>List&lt;NetworkLink&gt;</code> is retrieved from the <code>GeographyModel</code> and then supplied to a <code>MetaMap</code> to get the required additional information.</p>
  
  <p>What I want to do is try and adhere to the Open / Closed Principle by adding information each <code>NetworkLink</code> by creating <code>MetaMap</code> objects, but have somewhat got my knickers in a twist as to how to do this!</p>
  
  <p>Below is the code for the <code>MetaMap</code>.</p>
  
  <pre><code>public class MetaMap&lt;T&gt; {
  
  private final String name;
  private final Map&lt;NetworkLink, List&lt;T&gt;&gt; metaData;
  private final Map&lt;T, Set&lt;NetworkLink&gt;&gt; reverseLookup;
  private final List&lt;T&gt; fallback;
  private final List&lt;T&gt; information;
  
  public MetaMap(String name, T fallback){
      this.name = name;
      this.metaData = new HashMap&lt;&gt;();
      this.reverseLookup = new HashMap&lt;&gt;();
      this.fallback = new ArrayList&lt;&gt;();
      this.fallback.add(fallback);
      this.information = new ArrayList&lt;&gt;();
  }
  
  /**
   * Returns an identifier giving the information contained in this map
   *
   * @return
   */
  public String getName() {
      return name;
  }
  
  /**
   * Marks from origin to destination with information of type T
   *
   * @param line
   * @param information
   */
  public void markLineFragment(RunningLine line, T information) {
      line.getLinks().stream().map((link) -&gt; {
          if(!metaData.containsKey(link)) {
              metaData.put(link, new ArrayList&lt;&gt;());
          }
          return link;            
      }).forEach((link) -&gt; {
          metaData.get(link).add(information);
      });
  
      if(!reverseLookup.containsKey(information)) {
          reverseLookup.put(information, new HashSet&lt;&gt;());
      }
  
      reverseLookup.get(information).addAll(line.getLinks());
  }
  
  /**
   * Returns the information on the given NetworkLink
   *
   * @param link
   * @return
   */
  public List&lt;T&gt; getInformation(NetworkLink link) {
      return metaData.getOrDefault(link, fallback);
  }
  
  /**
   * Returns the information associated with the given line fragment
   * @param line
   * @return 
   */
  
  public List&lt;T&gt; getInformation(RunningLine line) {
      Set&lt;T&gt; resultSet = new HashSet();
  
      line.getLinks().stream().forEach((link) -&gt; {
          List&lt;T&gt; result = getInformation(link);
  
          resultSet.addAll(result);
      });
  
      return new ArrayList&lt;&gt;(resultSet);
  }
  
  /**
   * Returns all of the matching links which match the given information
   * @param information
   * @return 
   */
  
  public List&lt;NetworkLink&gt; getMatchingLinks(T information) {
      return new ArrayList&lt;&gt;(reverseLookup.get(information));
  }
  
  public void addInformation(T info) {
      information.add(info);
  }
  
  public void removeInformation(T info) {
      information.remove(info);
  }
  </code></pre>
  
  <p>Now... the problem I have is that as I expand the program, each new part will require a new <code>MetaMap</code> which is derived from <code>GeographyModel</code>.</p>
  
  <p>I want to follow the OCP and SRP as I am adding capabilities the program, but get a touch stuck as to implementation / combining the two concepts. A couple of thoughts do occur... </p>
  
  <p>I could get each new model requiring a <code>MetaMap</code> to register itself with the <code>GeographyModel</code>, but fear I would be violating the SRP. Each new prgoram feature could own a <code>MetaMap</code> and maintain it, but that would require querying the <code>GeographyModel</code> in the first place.</p>
  
  <p>Any ideas how I could approach this?</p>