/**
   * 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
 /** {@inheritDoc} */
 public void removeHostListener(HostListener listener) {
   /*
    * XXX: if a disconnect method is added, make sure it calls
    * this method to unregister this object from the watcher. otherwise,
    * an unused MonitoredHostProvider instance may go uncollected.
    */
   synchronized (listeners) {
     listeners.remove(listener);
     if (listeners.isEmpty() && (task != null)) {
       task.cancel();
       task = null;
     }
   }
 }
  /** Fire hostDisconnectEvent events. */
  void fireDisconnectedEvents() {
    ArrayList registered = null;
    HostEvent ev = null;

    synchronized (listeners) {
      registered = (ArrayList) listeners.clone();
    }

    for (Iterator i = registered.iterator(); i.hasNext(); /* empty */ ) {
      HostListener l = (HostListener) i.next();
      if (ev == null) {
        ev = new HostEvent(this);
      }
      l.disconnected(ev);
    }
  }
  /**
   * Fire VmStatusChangeEvent events to HostListener objects
   *
   * @param active Set of Integer objects containing the local Vm Identifiers of the active JVMs
   * @param started Set of Integer objects containing the local Vm Identifiers of new JVMs started
   *     since last interval.
   * @param terminated Set of Integer objects containing the local Vm Identifiers of terminated JVMs
   *     since last interval.
   */
  private void fireVmStatusChangedEvents(Set active, Set started, Set terminated) {
    ArrayList registered = null;
    VmStatusChangeEvent ev = null;

    synchronized (listeners) {
      registered = (ArrayList) listeners.clone();
    }

    for (Iterator i = registered.iterator(); i.hasNext(); /* empty */ ) {
      HostListener l = (HostListener) i.next();
      if (ev == null) {
        ev = new VmStatusChangeEvent(this, active, started, terminated);
      }
      l.vmStatusChanged(ev);
    }
  }
  public int propose(int seq, Operation op) throws RemoteException {

    if (!work) return seq;

    boolean decided = false;

    while (!decided) {

      seq++;

      ArrayList<KeyValueServerInterface> list = getServersList();

      int count = 0;

      int max = -1;

      for (KeyValueServerInterface server : list) {

        Instance ins = server.prepare(op.op_num, seq);

        if (ins != null) {
          count++;
          if (ins.n_a > max) {

            max = ins.n_a;
            // content = ins.content;
            op.content = ins.content;
          }
        }
      }
      if (count > (list.size() / 2)) {

        if (sendAllAccept(op.op_num, seq, op.content, list)) {

          for (KeyValueServerInterface server : list) {

            server.decide(seq, op);
          }

          decided = true;
        }
      }
    }

    return seq;
  }
 /** {@inheritDoc} */
 public void addHostListener(HostListener listener) {
   synchronized (listeners) {
     listeners.add(listener);
     if (task == null) {
       task = new NotifierTask();
       timer.schedule(task, 0, interval);
     }
   }
 }
  /**
   * 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 ArrayList<KeyValueServerInterface> getServersList() throws RemoteException {
    //
    ArrayList<KeyValueServerInterface> res = new ArrayList();

    try {
      Registry registry = LocateRegistry.getRegistry();
      String[] name = registry.list();
      for (String str : name) {

        // if( str.equals(server_name) ) continue;

        KeyValueServerInterface obj = (KeyValueServerInterface) registry.lookup(str);
        res.add(obj);
      }

    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
    return res;
  }
  /**
   * create a 1-d String array from a network, for easy transmission to R. each element in the array
   * is a string, with format sourceNode::targetNode::edgeType
   *
   * @param network the network to convert to a string
   * @return an array of strings representing a network
   */
  protected String[] networkToStringArray(Network network) {
    Interaction[] interactions = network.getInteractions();
    ArrayList<String> list = new ArrayList<String>();

    // System.out.println ("networkToStringArray, interaction ount: " + interactions.length);
    for (Interaction interaction : interactions) {
      String source = interaction.getSource();
      String target = interaction.getTarget();
      String type = interaction.getType();
      String combined = source + "::" + target + "::" + type;
      // System.out.println ("   interaction: " + combined);
      list.add(combined);
    } // for i

    String[] orphanNodes = network.getOrphanNodes();
    // System.out.println ("networkToStringArray, orphanCount: " + orphanNodes.length);
    for (String orphanNode : orphanNodes) {
      // System.out.println ("    orphan: " + orphanNodes [i]);
      list.add(orphanNode);
    }

    return list.toArray(new String[0]);
  } // networkToStringArray
  public boolean sendAllAccept(
      int ins_num, int income_seq, String content, ArrayList<KeyValueServerInterface> list)
      throws RemoteException {

    int count = 0;

    for (KeyValueServerInterface server : list) {

      if (server.accept(ins_num, income_seq, content) != -1) count++;
    }

    if (count > (list.size() / 2)) return true;

    return false;
  }