/** {@inheritDoc} */
  @Override
  public Evidence[] mapFromTable(CyEdge edge, CyTable table) {
    if (edge == null) throw new NullPointerException("edge cannot be null");
    if (table == null) throw new NullPointerException("table cannot be null");

    Set<String> nonAnnotationColumns =
        new HashSet<String>(
            asList(
                CyNetwork.SUID,
                NETWORK_SUID,
                NETWORK_NAME,
                EDGE_SUID,
                BEL_STATEMENT,
                SUMMARY_TEXT,
                CITATION_ID,
                CITATION_NAME,
                CITATION_TYPE,
                SPECIES));

    Collection<CyRow> evidenceRows = table.getMatchingRows(EDGE_SUID, edge.getSUID());
    List<Evidence> evidences = new ArrayList<Evidence>(evidenceRows.size());
    if (!evidenceRows.isEmpty()) {
      for (CyRow evRow : evidenceRows) {
        Evidence e = new Evidence();
        e.belStatement = evRow.get(BEL_STATEMENT, String.class);
        e.summaryText = evRow.get(SUMMARY_TEXT, String.class);
        e.citation = new Citation();
        e.citation.id = evRow.get(CITATION_ID, String.class);
        e.citation.name = evRow.get(CITATION_NAME, String.class);
        e.citation.type = evRow.get(CITATION_TYPE, String.class);
        e.biologicalContext = new BiologicalContext();
        e.biologicalContext.speciesCommonName = evRow.get(SPECIES, String.class);
        e.biologicalContext.variedAnnotations = new HashMap<String, Object>();
        for (Entry<String, Object> columnValue : evRow.getAllValues().entrySet()) {
          if (nonAnnotationColumns.contains(columnValue.getKey())) continue;
          e.biologicalContext.variedAnnotations.put(columnValue.getKey(), columnValue.getValue());
        }
        evidences.add(e);
      }
    }

    return evidences.toArray(new Evidence[evidences.size()]);
  }
  /** {@inheritDoc} */
  @Override
  public void mapToTable(Graph graph, Edge edge, Evidence evidence, CyTable table) {
    if (graph == null) throw new NullPointerException("graph cannot be null");
    if (edge == null) throw new NullPointerException("edge cannot be null");
    if (evidence == null) throw new NullPointerException("evidence cannot be null");
    if (table == null) throw new NullPointerException("table cannot be null");
    if (graph.cyNetwork == null)
      throw new IllegalArgumentException("graph's cyNetwork cannot be null");
    if (edge.cyEdge == null) throw new IllegalArgumentException("edge's cyEdge cannot be null");

    CyNetwork cyN = graph.cyNetwork;
    CyEdge cyE = edge.cyEdge;

    CyRow networkRow = cyN.getRow(cyN);
    String networkName = networkRow.get(CyNetwork.NAME, String.class);
    CyRow row = table.getRow(SUIDFactory.getNextSUID());

    row.set(NETWORK_SUID, cyN.getSUID());
    row.set(NETWORK_NAME, networkName);
    row.set(EDGE_SUID, cyE.getSUID());
    row.set(BEL_STATEMENT, evidence.belStatement);
    row.set(SUMMARY_TEXT, evidence.summaryText);

    if (evidence.citation != null) {
      row.set(CITATION_TYPE, evidence.citation.type);
      row.set(CITATION_ID, evidence.citation.id);
      row.set(CITATION_NAME, evidence.citation.name);
    }

    if (evidence.biologicalContext != null) {
      // create any annotation columns that do not already exist
      BiologicalContext bc = evidence.biologicalContext;
      for (String varyingKey : bc.variedAnnotations.keySet()) {
        getOrCreateColumn(varyingKey, String.class, false, table);
      }

      // set annotation values
      row.set(SPECIES, bc.speciesCommonName);
      Map<String, Object> varying = bc.variedAnnotations;
      for (Entry<String, Object> entry : varying.entrySet()) {
        row.set(entry.getKey(), getOrEmptyString(entry.getKey(), varying));
      }
    }
  }