/**
   * create a 1-d String array from a network, for easy transmission to R. triples (source,
   * edgeType, target) are filled in to an array of length 3 * # of interactions
   *
   * @param network a gaggle network
   * @return the edge attributes of the network as a string array
   */
  protected String[] networkEdgeAttributesToStringArray(Network network) {
    Interaction[] interactions = network.getInteractions();
    String source, target, type;
    String[] attributeNames = network.getEdgeAttributeNames();
    ArrayList<String> list = new ArrayList<String>();

    for (Interaction interaction : interactions) {
      source = interaction.getSource();
      type = interaction.getType();
      target = interaction.getTarget();
      String edgeName = source + " (" + type + ") " + target;
      String terseEdgeName = source + "::" + target + "::" + type;
      for (String name : attributeNames) {
        HashMap hash = network.getEdgeAttributes(name);
        if (hash.containsKey(edgeName)) {
          Object value = hash.get(edgeName);
          StringBuffer sb = new StringBuffer();
          sb.append(terseEdgeName);
          sb.append("::");
          sb.append(name);
          sb.append("::");
          sb.append(value.toString());
          list.add(sb.toString());
        } else {
          System.out.println("no " + name + " attribute for " + edgeName);
        }
      } // for a
    } // for r

    return list.toArray(new String[0]);
  } // networkEdgeAttributesToStringArray
  public void dump() throws RemoteException {
    int num_ins = instances.size();

    System.out.println(getServerName() + ":");

    for (int i = 1; i <= num_ins; i++) {
      Instance tmp = instances.get(i);

      System.out.println(i + ": " + tmp.toString());
    }

    return;
  }
  public int accept(int ins_num, int income_seq, String content) throws RemoteException {
    if (!work) return -1;

    Instance res = instances.get(ins_num);

    if (res == null) return -1;
    else {

      if (income_seq >= res.n_p) {

        res.n_p = income_seq;

        res.n_a = income_seq;

        res.content = content;

        res.decided = true;

        INS_NUM++;

        return income_seq;
      }
    }

    return -1;
  }
  public KeyValueServerInterfaceImpl(String server_name, int instance_capibility)
      throws RemoteException {
    this.server_name = server_name;
    // loghelper = new LogHelper(server_name+"_log");
    INS_NUM = 0;

    work = true;

    for (int i = 1; i <= instance_capibility; i++) instances.put(new Integer(i), new Instance());
  }
  /**
   * create a 1-d String array from a network's node attributes, for easy transmission to R. use
   * this format for each attribute of each node: nodeName::attributeName::value
   *
   * @param network a gaggle network
   * @return the network's node attributes as a string array
   */
  protected String[] networkNodeAttributesToStringArray(Network network) {
    String[] attributeNames = network.getNodeAttributeNames();
    // System.out.println (" nnatsa, attribute name count: " + attributeNames.length);
    ArrayList<String> list = new ArrayList<String>();

    for (String attributeName : attributeNames) {
      // System.out.println (" nnatsa, attribute name: " + attributeName);
      HashMap attributeHash = network.getNodeAttributes(attributeName);
      // can't remove this warning until Network is genericized in next api release:
      String[] nodeNames = (String[]) attributeHash.keySet().toArray(new String[0]);
      for (String nodeName : nodeNames) {
        // System.out.println (" nnatsa, node name: " + nodeName);
        Object value = attributeHash.get(nodeName);
        String terseForm = nodeName + "::" + attributeName + "::" + value.toString();
        list.add(terseForm);
      } // for n
    } // for i

    return list.toArray(new String[0]);
  } // networkEdgeAttributesToStringArray
  public Instance prepare(int ins_num, int income_seq) throws RemoteException {
    if (!work) return null;

    Instance res = instances.get(ins_num);

    if (res == null) return null;
    else {

      if (income_seq > res.n_p) {

        res.n_p = income_seq;

        return res;
      } else return null;
    }
  }
  public void decide(int income_seq, Operation op) throws RemoteException {

    // set corresponding Op decided, assume no collision happens

    if (!work) return;

    if (op == null) return;

    Instance ins = instances.get(op.op_num);

    if (!ins.decided) {

      ins.decided = true;

      INS_NUM++;

      ins.n_a = income_seq;

      ins.content = op.content;
    }

    return;
  }