public void mapEdgeColumn(final EncoreInteraction interaction, final CyRow row) {

    final Set<String> exp = interaction.getExperimentToPubmed().keySet();
    row.set(DETECTION_METHOD_ID, new ArrayList<String>(exp));

    final List<CrossReference> pubIDs = interaction.getPublicationIds();
    final List<String> pubIdList = new ArrayList<String>();
    final List<String> pubDBList = new ArrayList<String>();
    for (CrossReference pub : pubIDs) {
      pubIdList.add(pub.getIdentifier());
      pubDBList.add(pub.getDatabase());
    }
    if (pubIdList.isEmpty() == false) row.set(PUB_ID, pubIdList);
    if (pubDBList.isEmpty() == false) row.set(PUB_DB, pubDBList);

    // Interaction (use UniqueID)
    row.set(CyEdge.INTERACTION, interaction.getMappingIdDbNames());

    final List<Confidence> scores = interaction.getConfidenceValues();
    for (Confidence c : scores) {
      String type = c.getType();
      String value = c.getValue();

      if (row.getTable().getColumn(type) == null)
        row.getTable().createColumn(type, Double.class, true);

      try {
        double doubleVal = Double.parseDouble(value);
        row.set(type, doubleVal);
      } catch (NumberFormatException e) {
        // logger.warn("Invalid number string: " + value);
        // Ignore invalid number
      }
    }
  }
  public void mapNodeColumn(final String[] entries, final CyRow sourceRow, final CyRow targetRow) {
    this.isSelfEdge = false;

    // Primary ID sets
    final Map<String, String> accsSource = createNames(entries[0]);
    processNames(sourceRow, accsSource);

    // ALT and Aliases
    final Map<String, List<String>> otherSource = createOtherNames(entries[2], entries[4]);
    processOtherNames(sourceRow, otherSource);

    if (currentGeneName != null) sourceRow.set(PREDICTED_GENE_NAME, currentGeneName);
    else {
      guessHumanReadableName(sourceRow);
    }
    setSpecies(entries[9], sourceRow);

    if (!isSelfEdge) {
      final Map<String, String> accsTarget = createNames(entries[1]);
      processNames(targetRow, accsTarget);
      final Map<String, List<String>> otherTarget = createOtherNames(entries[3], entries[5]);
      processOtherNames(targetRow, otherTarget);
      if (currentGeneName != null) targetRow.set(PREDICTED_GENE_NAME, currentGeneName);
      else {
        guessHumanReadableName(targetRow);
      }
      setSpecies(entries[10], targetRow);
    }

    // For 2.7 data
    if (entries.length > 15) {
      //			addListColumn(sourceRow, entries[16], "Biological Role", String.class);
      //			addListColumn(targetRow, entries[17], "Biological Role", String.class);
      //
      //			addListColumn(sourceRow, entries[18], "Experimental Role", String.class);
      //			addListColumn(targetRow, entries[19], "Experimental Role", String.class);

      addListColumn(sourceRow, entries[20], INTERACTOR_TYPE, String.class);
      addListColumn(targetRow, entries[21], INTERACTOR_TYPE, String.class);

      addListColumn(sourceRow, entries[22], "Xref", String.class);
      addListColumn(targetRow, entries[23], "Xref", String.class);

      addSimpleListColumn(sourceRow, entries[25], "Annotations");
      addSimpleListColumn(targetRow, entries[26], "Annotations");

      addSimpleListColumn(sourceRow, entries[36], "Features");
      addSimpleListColumn(targetRow, entries[38], "Features");

      //			addListColumn(sourceRow, entries[40], "Participant Detection Method", String.class);
      //			addListColumn(targetRow, entries[41], "Participant Detection Method", String.class);
    }
  }
  private final void setSpecies(final String speciesText, CyRow row) {
    // Pick first entry only.
    final String[] entries = SPLITTER.split(speciesText);
    final String[] values = parseValues(entries[0]);

    if (values[1] != null) {
      row.set(TAXNOMY, values[1]);
    }

    if (values[2] != null) {
      row.set(TAXNOMY_NAME, values[2]);
    }
  }
  private boolean findHumanReadableName(
      final CyRow row, final List<String> attrList, Pattern pattern, boolean exist) {
    String candidateString = null;
    for (final String geneID : attrList) {
      if (pattern.matcher(geneID).find() == exist) {
        candidateString = geneID;
        break;
      }
    }
    if (candidateString != null) {
      if (candidateString.contains("_")) {
        final String firstPart = candidateString.split("_")[0];
        for (String candidate : attrList) {
          if (candidate.equalsIgnoreCase(firstPart)) {
            candidateString = firstPart;
            break;
          }
        }
      }
      row.set(PREDICTED_GENE_NAME, candidateString);
      return true;
    }

    return false;
  }
  private void processSpecies(CyRow row, CrossReference ref) {
    if (ref != null) {
      final String name = ref.getText();
      final String speciesID = ref.getIdentifier();

      row.set(TAXNOMY, speciesID);
      row.set(TAXNOMY_NAME, name);
    }
  }
  /** {@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));
      }
    }
  }
  private void mergeRow(String keyName, CyRow sourceRow, CyRow targetRow) {
    for (CyColumn column : sourceRow.getTable().getColumns()) {
      if (cancelled) return;

      String columnName = column.getName();

      if (columnName.equals(keyName)) continue;

      Class<?> type = column.getType();

      if (type.equals(List.class)) {
        Class<?> elementType = column.getListElementType();
        List<?> list = sourceRow.getList(columnName, elementType);
        targetRow.set(columnName, list);
      } else {
        Object value = sourceRow.get(columnName, type);
        targetRow.set(columnName, value);
      }
    }
  }
  private final void addListColumn(
      final CyRow row, final String val, final String columnName, final Class<?> listType) {
    if (val == null || val.equals("-")) {
      return;
    }

    String newColName = null;

    // Create column if necessary
    if (columnName != null) {
      if (row.getTable().getColumn(columnName) == null) {
        row.getTable().createListColumn(columnName, listType, false);
        row.getTable().createListColumn(columnName + " ID", String.class, false);
      }
      newColName = columnName;
    }

    final String[] entries = SPLITTER.split(val);

    final List<String> ids = new ArrayList<String>();
    final List<String> descriptions = new ArrayList<String>();
    for (final String entry : entries) {
      final String[] contents = parseValues(entry);
      if (newColName == null) {
        if (row.getTable().getColumn(contents[0]) == null) {
          row.getTable().createListColumn(contents[0], listType, false);
          row.getTable().createListColumn(contents[0] + " ID", String.class, false);
        }
        newColName = contents[0];
      }
      if (contents[1] != null) ids.add(contents[1]);
      if (contents[2] != null) descriptions.add(contents[2]);
    }
    if (!ids.isEmpty()) row.set(newColName + " ID", ids);
    if (!descriptions.isEmpty()) row.set(newColName, descriptions);
  }
  private void processOtherNames(CyRow row, final Map<String, List<String>> accs) {
    for (String originalDBName : accs.keySet()) {

      final String dbName = validateNamespace(originalDBName);

      if (row.getTable().getColumn(dbName) == null)
        row.getTable().createListColumn(dbName, String.class, false);

      List<String> currentList = row.getList(dbName, String.class);
      if (currentList == null) currentList = new ArrayList<String>();

      final Set<String> nameSet = new HashSet<String>(currentList);
      final List<String> names = accs.get(originalDBName);
      nameSet.addAll(names);
      row.set(dbName, new ArrayList<String>(nameSet));
    }
  }
  /**
   * Add a single entry
   *
   * @param row
   * @param val
   * @param columnName
   */
  private final void addSingleColumn(
      final CyRow row, final String val, final String columnName, final Class<?> dataType) {
    // Ignore invalid entry.
    if (val == null || val.equals("-")) {
      return;
    }

    // Create column if necessary
    if (row.getTable().getColumn(columnName) == null) {
      row.getTable().createColumn(columnName, dataType, false);
    }

    Object newValue = val;
    if (dataType == Boolean.class) newValue = Boolean.parseBoolean(val);

    row.set(columnName, newValue);
  }
  @Override
  public boolean handleIt(
      final CyIdentifiable to,
      final CyColumn toColumn,
      final Map<CyIdentifiable, CyColumn> mapFromGOFromAttr) {

    if (to == null || toColumn == null || mapFromGOFromAttr == null) {
      throw new java.lang.NullPointerException("All parameters should not be null.");
    }

    final CyTable table = toColumn.getTable();
    final CyRow row = table.getRow(to.getSUID());
    final ColumnType type = ColumnType.getType(toColumn);

    if (type == ColumnType.STRING) {
      final String toValue = row.get(toColumn.getName(), String.class);
      final Set<String> values = new TreeSet<String>();
      values.add(toValue);

      for (Map.Entry<CyIdentifiable, CyColumn> entry : mapFromGOFromAttr.entrySet()) {
        final CyIdentifiable from = entry.getKey();
        final CyColumn fromColumn = entry.getValue();
        final CyRow fromRow = fromColumn.getTable().getRow(from.getSUID());

        // TODO figure out which network to be using
        String fromValue = fromRow.get(fromColumn.getName(), String.class);
        if (fromValue != null) {
          values.add(fromValue.toString());
        }
      }

      StringBuilder str = new StringBuilder();
      for (String v : values) {
        str.append(v + ";");
      }

      str.deleteCharAt(str.length() - 1);
      row.set(toColumn.getName(), str.toString());

      return true;
    }

    // FIXME: how about Integer, Double, Boolean?
    return false;
  }
  private void guessHumanReadableName(final CyRow row) {
    boolean found = false;

    // Special handler for STRING. This is a hack...
    if (row.getTable().getColumn(STRING_ATTR_NAME) != null) {
      final List<String> stringList = row.getList(STRING_ATTR_NAME, String.class);
      if (stringList != null) found = findHumanReadableName(row, stringList, ncbiPattern, true);
    }

    if (found) return;

    // try NCBI
    if (row.getTable().getColumn(ENTREZ_GENE_ATTR_NAME) != null) {
      final List<String> ncbiList = row.getList(ENTREZ_GENE_ATTR_NAME, String.class);
      if (ncbiList != null) found = findHumanReadableName(row, ncbiList, ncbiPattern, true);
    }
    if (found) return;

    // Try Uniprot
    List<String> uniprotList = null;
    if (row.getTable().getColumn(UNIPROT_ATTR_NAME) != null) {
      uniprotList = row.getList(UNIPROT_ATTR_NAME, String.class);
      if (uniprotList != null) found = findHumanReadableName(row, uniprotList, exact1Pattern, true);
    }
    if (found) return;

    if (uniprotList != null) found = findHumanReadableName(row, uniprotList, uniprotPattern, false);

    if (found) return;

    // Unknown
    if (row.getTable().getColumn("unknown") != null) {
      final List<String> unknownList = row.getList("unknown", String.class);
      if (unknownList != null)
        found = findHumanReadableName(row, unknownList, uniprotPattern, false);
    }
    if (found) return;

    if (found == false) {
      // Give up. Use primary key
      row.set(PREDICTED_GENE_NAME, row.get(CyNetwork.NAME, String.class));
    }
  }
  /**
   * Split the entry by the delimiter and simply creates list column from the values.
   *
   * @param row
   * @param val
   * @param columnName
   */
  private final void addSimpleListColumn(
      final CyRow row, final String val, final String columnName) {
    // Ignore invalid entry.
    if (val == null || val.equals("-")) {
      return;
    }

    // Create column if necessary
    if (row.getTable().getColumn(columnName) == null) {
      row.getTable().createListColumn(columnName, String.class, false);
    }

    final String[] entries = SPLITTER.split(val);
    final List<String> ids = new ArrayList<String>();
    for (final String entry : entries) {
      if (entry != null) {
        final String newEntry = entry.replaceAll("\"", "");
        ids.add(newEntry);
      }
    }
    if (!ids.isEmpty()) row.set(columnName, ids);
  }
  public void handleEvent(RowsSetEvent e) {

    final CyTable local = e.getSource();

    synchronized (lock) {
      final List<CyTable> sharedList = tables.get(local);

      for (CyTable shared : sharedList) {
        for (RowSetRecord record : e.getColumnRecords(columnName)) {
          // assume payload collection is for same column
          final CyRow r = shared.getRow(record.getRow().get(CyIdentifiable.SUID, Long.class));
          if (r != null) {
            final Object name = record.getValue();
            String sharedName = r.get(sharedColumnName, String.class);
            if (sharedName == null) {
              r.set(sharedColumnName, name);
            }
          }
        }
      }
    }
  }
    @Override
    public void run(TaskMonitor taskMonitor) throws Exception {
      CaseList caseList = (CaseList) caseSetComboBox.getSelectedItem();
      Object[] profiles = profileList.getSelectedValues();
      String geneSymbolField = (String) geneSymbolComboBox.getSelectedItem();
      // update the configuration to store this field
      MondrianApp app = MondrianApp.getInstance();
      CyNetwork currentNetwork = app.getAppManager().getCurrentNetwork();

      // call the next two lines in the right order!
      app.getMondrianConfiguration()
          .setNetworkGeneSymbolAttr(currentNetwork.getSUID(), geneSymbolField);
      Map<String, Long> geneSymbolMap =
          app.getMondrianConfiguration().getGeneNodeMap(currentNetwork.getSUID());

      List<String> genes = new ArrayList<String>(geneSymbolMap.keySet());

      // Extract data from web service
      int p = 1;
      List<GeneticProfile> profileList = new ArrayList<GeneticProfile>();
      List<MondrianCyTable> importedTables = new ArrayList<MondrianCyTable>();
      CyNetwork network = app.getAppManager().getCurrentNetwork();
      CancerStudy study = (CancerStudy) cancerStudyComboBox.getSelectedItem();
      for (Object obj : profiles) {
        GeneticProfile profile = (GeneticProfile) obj;
        profileList.add(profile);
        taskMonitor.setStatusMessage("Loading genetic profile: " + profile.getName());
        taskMonitor.setProgress(p++ / (double) profiles.length);

        CyTable table =
            MondrianApp.getInstance()
                .getTableFactory()
                .createTable(profile.getName(), CyIdentifiable.SUID, Long.class, true, true);
        DataTypeMatrix matrix = portalClient.getProfileData(caseList, profile, genes);

        List<String> dataColNames = matrix.getDataColNames();
        for (String colName : dataColNames) {
          if (profile.getType() == GENETIC_PROFILE_TYPE.MUTATION_EXTENDED) {
            table.createColumn(colName, String.class, false);
          } else {
            table.createColumn(colName, Double.class, false);
          }
        }

        // Add rows
        for (String rowName : matrix.getRowNames()) {
          long suid = geneSymbolMap.get(rowName);
          CyRow row = table.getRow(suid);
          // row.set("selected", currentNetwork.getDefaultNodeTable().getRow(suid).get("selected",
          // Boolean.class));
          // row.set(geneSymbolField, rowName);
          int i = 0;
          for (String colName : dataColNames) {
            row.set(colName, matrix.getDataRow(rowName).get(i++));
          }
        }
        log.debug(
            "Loading genetic profile: "
                + profile.getName()
                + "; Insert Table: "
                + matrix.getNumRows()
                + ", "
                + matrix.getDataColNames().size());

        MondrianCyTable mondrianCyTable = new MondrianCyTable(study, profile, caseList, table);
        importedTables.add(mondrianCyTable);
        //
      }
      app.getMondrianConfiguration().registerMondrianTables(network, importedTables);
      // app.getMondrianConfiguration().cbioDataImport(currentNetwork.getSUID(), profileList,
      // caseList);
    }
  private void mapEntry(final String[] entries) {
    // Set primary key for the table, which is DB Object ID
    final String primaryKeyValue = entries[DB_OBJ_ID];

    final CyRow row = table.getRow(primaryKeyValue);
    row.set(CyNetwork.NAME, primaryKeyValue);

    // Check namespace
    final String namespace = NAMESPACE_MAP.get(entries[ASPECT]);

    for (int i = 0; i < EXPECTED_COL_COUNT; i++) {
      final GeneAssociationTag tag = GeneAssociationTag.values()[i];

      switch (tag) {

          // Evidence code and GO ID should be organized by namespace.
        case GO_ID:
          String goidString = entries[i];
          if (this.termIDList != null) goidString = convertToName(goidString);

          List<String> currentList = row.getList(namespace, String.class);
          if (currentList == null) currentList = new ArrayList<String>();

          if (currentList.contains(goidString) == false) currentList.add(goidString);
          row.set(namespace, currentList);
          break;

        case EVIDENCE:
        case DB_REFERENCE:
          final String value = entries[i];
          String columnName = namespace;
          if (tag == GeneAssociationTag.EVIDENCE) columnName = columnName + EVIDENCE_SUFFIX;
          else columnName = columnName + REFERENCE_SUFFIX;

          List<String> valueList = row.getList(columnName, String.class);
          if (valueList == null) valueList = new ArrayList<String>();
          if (valueList.contains(value) == false) valueList.add(value);
          row.set(columnName, valueList);

          break;
        case TAXON:
          final String taxID = entries[i].split(":")[1];
          final String taxName = speciesMap.get(taxID);
          if (taxName != null) row.set(tag.toString(), taxName);
          else if (taxID != null) row.set(tag.toString(), taxID);
          break;

        case ASPECT:
          // Ignore these lines
          break;

        case DB_OBJECT_ID:
        case DB_OBJECT_SYMBOL:
        case DB_OBJECT_SYNONYM:
          // Create consolidated id list attribute.
          List<String> synList = row.getList(SYNONYM_COL_NAME, String.class);
          if (synList == null) synList = new ArrayList<String>();

          if (tag == GeneAssociationTag.DB_OBJECT_SYNONYM) {
            final String[] vals = entries[i].split(LIST_DELIMITER);
            for (String val : vals) {
              if (synList.contains(val) == false) synList.add(val);
            }
          } else {
            if (synList.contains(entries[i]) == false) synList.add(entries[i]);
          }
          row.set(SYNONYM_COL_NAME, synList);
          break;
        default:
          if (LIST_INDEX.contains(i + 1)) {
            final String[] vals = entries[i].split(LIST_DELIMITER);

            List<String> listVals = row.getList(tag.toString(), String.class);
            if (listVals == null) listVals = new ArrayList<String>();
            for (String val : vals) {
              if (listVals.contains(val) == false) listVals.add(val);
            }
            row.set(tag.toString(), listVals);
          } else row.set(tag.toString(), entries[i]);
          break;
      }
    }
  }
  public void mapEdgeColumn(
      final String[] entries,
      final CyRow row,
      final CyEdge edge,
      final String sourceName,
      final String targetName) {

    // Column 7: Detection method
    final String[] detectionMethods = SPLITTER.split(entries[6]);
    final List<String> methods = new ArrayList<String>();
    final List<String> methodID = new ArrayList<String>();
    for (final String entry : detectionMethods) {
      final String[] methodContents = parseValues(entry);
      if (methodContents[1] != null) methodID.add(methodContents[1]);
      if (methodContents[2] != null) methods.add(methodContents[2]);
    }
    if (!methods.isEmpty()) row.set(DETECTION_METHOD_NAME, methods);
    if (!methodID.isEmpty()) row.set(DETECTION_METHOD_ID, methodID);

    // Column 8: Authors
    final String[] authorsParts = SPLITTER.split(entries[7]);
    final List<String> authors = new ArrayList<String>();
    for (final String entry : authorsParts) {
      String updatedAuthor = entry.replaceAll("\"", "");
      authors.add(updatedAuthor);
    }
    if (!authors.isEmpty()) row.set(AUTHOR, authors);

    final List<String> pubIdList = new ArrayList<String>();
    final List<String> pubDBList = new ArrayList<String>();
    final String[] pubID = SPLITTER.split(entries[8]);
    for (final String entry : pubID) {
      String id = parseValues(entry)[1];
      String db = parseValues(entry)[0];
      if (id != null && db != null) {
        pubDBList.add(db);
        pubIdList.add(id);
      }
    }

    if (!pubIdList.isEmpty()) row.set(PUB_ID, pubIdList);
    if (!pubDBList.isEmpty()) row.set(PUB_DB, pubDBList);

    final String[] dbNames = SPLITTER.split(entries[12]);
    row.set(SOURCE_DB, parseValues(dbNames[0])[0]);

    // Interaction Types - Use first one as primary type.
    final String[] typeParts = SPLITTER.split(entries[11]);
    final List<String> types = new ArrayList<String>();
    for (final String entry : typeParts) {
      final String type = parseValues(entry)[2];
      if (type != null) types.add(type);
    }
    if (!types.isEmpty()) {
      row.set(INTERACTION_TYPE, types);
      row.set(PRIMARY_INTERACTION_TYPE, types.get(0));
    }

    // Set interaction: this is an ID.
    final String[] interactionID = SPLITTER.split(entries[13]);
    final String interaction = parseValues(interactionID[0])[1];
    row.set(CyEdge.INTERACTION, interaction);

    // Create name
    row.set(CyNetwork.NAME, sourceName + " (" + interaction + ") " + targetName);

    final String[] scores = SPLITTER.split(entries[14]);
    for (String score : scores) {
      final String[] scoreArray = parseValues(score);
      String scoreType = "Confidence-Score-" + scoreArray[0];
      String value = scoreArray[1];
      if (value == null) {
        continue;
      }

      if (row.getTable().getColumn(scoreType) == null)
        row.getTable().createColumn(scoreType, Double.class, true);

      try {
        double doubleVal = Double.parseDouble(value);
        row.set(scoreType, doubleVal);
      } catch (NumberFormatException e) {
        // logger.warn("Invalid number string: " + value);
        // Ignore invalid number
      }
    }

    // For MITAB 2.7
    if (entries.length > 15) {
      addListColumn(row, entries[16], "Source Biological Role", String.class);
      addListColumn(row, entries[17], "Target Biological Role", String.class);
      addListColumn(row, entries[18], "Source Experimental Role", String.class);
      addListColumn(row, entries[19], "Target Experimental Role", String.class);
      addListColumn(row, entries[40], "Source Participant Detection Method", String.class);
      addListColumn(row, entries[41], "Target Participant Detection Method", String.class);

      addListColumn(row, entries[15], "Complex Expansion", String.class);
      addListColumn(row, entries[24], "Xref", String.class);

      addSimpleListColumn(row, entries[27], "Annotation");

      addListColumn(row, entries[28], "Host Organism Taxonomy", String.class);
      addSimpleListColumn(row, entries[29], "Parameters");

      addSingleColumn(row, entries[30], "Creation Date", String.class);
      addSingleColumn(row, entries[31], "Update Date", String.class);

      addSingleColumn(row, entries[35], "Negative", Boolean.class);
    }
  }