/**
   * Tests that ConnectionManager manages the same instance that was added using the {@link
   * ConnectionManager#addConnection} method.
   */
  public void testSameInstanceAfterAdd() throws Exception {
    Util.clearConnections();
    assertEquals(0, ConnectionList.getDefault().getConnections().length);

    DatabaseConnection dbconn =
        new DatabaseConnection(
            "org.bar.BarDriver",
            "bar_driver",
            "jdbc:bar:localhost",
            "schema",
            "user",
            "password",
            true);
    // We are testing ConnectionList.addConnection(), but that doesn't return a DataObject.
    DataObject dbconnDO = DatabaseConnectionConvertor.create(dbconn);

    WeakReference<DataObject> dbconnDORef = new WeakReference<DataObject>(dbconnDO);
    dbconnDO = null;
    for (int i = 0; i < 50; i++) {
      System.gc();
      if (dbconnDORef.get() == null) {
        break;
      }
    }

    assertEquals(1, ConnectionList.getDefault().getConnections().length);

    // This used to fail as described in issue 75204.
    assertSame(dbconn, ConnectionList.getDefault().getConnections()[0]);

    Util.clearConnections();
    WeakReference<DatabaseConnection> dbconnRef = new WeakReference<DatabaseConnection>(dbconn);
    dbconn = null;
    assertGC("Should be able to GC dbconn", dbconnRef);
  }
 private void createCycles(int count) {
   int[] nodeIndexes = new int[connections.size()];
   for (int index = 0; index < connections.size(); index++) {
     nodeIndexes[index] = index;
   }
   // Shuffle the list of nodes.
   for (int index = connections.size() - 1; index > 0; index--) {
     int other = rand.nextInt(index);
     int temp = nodeIndexes[other];
     nodeIndexes[other] = nodeIndexes[index];
     nodeIndexes[index] = temp;
   }
   double netSize = connections.size() / count;
   int network = 1;
   int firstIndex = 0;
   double nextNetwork = netSize;
   String netName = "Network" + network;
   for (int index = 1; index <= netSize; index++) {
     connections.get(nodeIndexes[index - 1]).setNetwork("Network" + network);
     if (index > nextNetwork - 0.5) {
       // We have finished all the nodes of a network.
       // Add link between previous node and "firstNode"
       // and store the network in "cycles"
       addLink(nodeIndexes[index - 1], nodeIndexes[firstIndex], "Network" + network);
       firstIndex = index;
       cycles.put(netName, new Network(links, netName, connections));
       network++;
       netName = "Network" + network;
       nextNetwork = Math.ceil(network * netSize);
     } else {
       addLink(nodeIndexes[index - 1], nodeIndexes[index], netName);
     }
   }
 }
  // ***************** KeyListener ****************
  @Override
  public void keyPressed(KeyEvent e) {
    // TODO Auto-generated method stub
    if (e.getKeyCode() == 8) // if delete key is pressed
    {
      MoleculeComponent currentElement = elist.getSelected();
      if (currentElement != null) {
        // Clear any lines being drawn (cancel connections)
        drawBondLine = false;
        drawArrowLine = false;

        elist.removeSelected();
        mmc.view.displayAttributes(null);

        repaint();
      }

    } else if (e.getKeyCode() == e.VK_ESCAPE) // if user hits ESC
    {
      if (drawBondLine == true) // and there is a bond being drawn
      {
        drawBondLine = false; // cancel that bond
        repaint();
      }
    }
  }
  private void route(JsonObject message, int fromNode) {
    String text = message.getString("text", null);
    int from = message.getInt("from", -1);
    int to = message.getInt("to", -1);

    if (fromNode == from && to >= 0 && text != null) {
      SwingUtilities.invokeLater(
          () -> {
            messages.addPacket(from, to, text, getByNode(from).getNetwork());
          });
      if (to == 0) {
        for (int i = 0; i < connections.size(); i++) {
          Connection c = connections.get(i);
          if (c != null && links.isNeighbour(fromNode, c.getNode())) {
            send(c, text, from, to);
          }
        }
      } else {
        Connection c = getByNode(to);
        if (c != null && links.isNeighbour(from, to)) {
          send(c, text, from, to);
        }
      }
    }
  }
 private void addLink(int from, int to, String network) {
   int nodeA = connections.get(from).getNode();
   int nodeB = connections.get(to).getNode();
   System.out.println("Create link between " + nodeA + " and " + nodeB);
   if (!links.isNeighbour(nodeA, nodeB)) {
     links.addElement(new Link(nodeA, nodeB, network));
   }
 }
 private int nodeToIndex(int node) {
   int l = connections.size();
   for (int j = 0; j < l; j++) {
     if (connections.get(j).getNode() == node) {
       return j;
     }
   }
   return 0; // Should not happen
 }
 private Connection getByNode(int node) {
   for (int i = 0; i < connections.size(); i++) {
     Connection c = connections.get(i);
     if (c.getNode() == node) {
       return c;
     }
   }
   return null;
 }
  public void paintComponent(Graphics g) {
    clearScreen(g);
    drawGrid(g);
    drawElements(g);

    if (drawBondLine == true) {
      Bond.drawDrag(g, Color.MAGENTA, elist.getSelected(), currentX, currentY);
    }

    if (drawArrowLine == true) {
      Arrow.drawDrag(g, Color.BLUE, elist.getSelected(), currentX, currentY);
    }

    drawConnections(g);
  }
  public void addConnection(BufferedOutputStream os, InputStream isr, InetAddress a)
      throws HandshakeException {
    final Connection c = new Connection(os, isr);

    int setNode = c.getNode();
    boolean keep = false;
    if (session == c.getSession() && setNode != 0) {
      // Loop through the connections and find the node number
      for (int i = 0; i < connections.size(); i++) {
        Connection cc = connections.get(i);
        if (cc.getNode() == setNode) {
          // Keep old node Name
          c.setHostname(cc.getHostname());
          c.setNetwork(cc.getNetwork());
          final int actualNode = i;
          SwingUtilities.invokeLater(
              () -> {
                // This is not a structural modification so will not
                // cause Thread problems
                connections.set(actualNode, c);
              });
          keep = true;
          synchronized (queue) {
            // add the appropriate status reply
            queue.add(new ConnectMessage(c, -1, true));
          }
          break;
        }
      }
    }
    if (!keep) {
      if (started) {
        throw new HandshakeException("Cannot add new connections after the game has started");
      }
      c.setup(session);
      try {
        SwingUtilities.invokeAndWait(
            () -> {
              connections.addElement(c);
            });
      } catch (InvocationTargetException | InterruptedException e) {
        throw new HandshakeException("Failed to add new connection");
      }
      (new ConnectMessage(c, -1, true)).send();
    }
  }
  private void drawConnections(Graphics g) {
    ArrayList<MoleculeConnectorComponent> connections = elist.getBondsAndArrows();

    if (connections == null) return;

    for (MoleculeConnectorComponent c : connections) {
      c.draw(g, OBJECT_OFFSET, OBJECT_OFFSET_Y);
    }
  }
  private void drawElements(Graphics g) {
    if (elist.hasElements()) {
      // Smallest size is used for radius of circle so elements don't
      // get "squished in" when one of the axis is smaller than the other:
      int smallestSize = GRID_SPACING;
      if (GRID_SPACING > GRID_SPACING_Y) {
        smallestSize = GRID_SPACING_Y;
      }

      for (Element e : elist.getCoordinates()) {

        g.setColor(e.getColor());
        g.fillOval(
            e.getX() * GRID_SPACING + OBJECT_OFFSET / 4,
            e.getY() * GRID_SPACING_Y + OBJECT_OFFSET_Y / 4,
            smallestSize / 2,
            smallestSize / 2);
      }
    }
  }
  // This method can only be executed in the EDT so is safe from Connections
  // updates
  public void updateStatus() {
    // The first update triggers network building.
    if (!started) {
      started = true;
      int maxNets = Math.max(1, connections.size() / MIN_PER_NET);
      int numNets = Math.min((connections.size() + MAX_PER_NET - 1) / MAX_PER_NET, maxNets);
      createCycles(numNets);
      // Begin to check for messages.
      synchronized (queue) {
        this.start();
      }
    }
    int l = connections.size();
    List<String> texts = null;
    if (links.getOffset() != 0 && !links.isCheckwhois()) {
      texts = new ArrayList<String>();
      Texts.choose_messages(texts, l, links.getCorruptionRate() > 0);
    }
    // mark any current messages out of date
    startTime = System.currentTimeMillis();

    synchronized (queue) {
      for (int i = 0; i < l; i++) {
        Connection c = connections.get(i);
        if (c != null) {
          if (links.getOffset() == 0) {
            queue.add(new TaskMessage(c, -1, links));
          } else {
            int recipient = cycles.get(c.getNetwork()).offsetNode(c.getNode(), links.getOffset());
            System.out.println("Node:" + c.getNode() + "sending to: " + recipient);
            if (links.isCheckwhois()) {
              String unknown = connections.get(nodeToIndex(recipient)).getHostname();
              queue.add(new TaskMessage(c, -1, links, unknown));
            } else {
              queue.add(new TaskMessage(c, -1, links, recipient, texts.get(i)));
            }
          }
        }
      }
    }
  }
  @Override
  public void mousePressed(MouseEvent e) {
    elist.setSelected(null);

    if (e.getButton() == 1) {
      leftPressed = true;
      rightPressed = false;

      MoleculeComponent clickedOn = elist.getClickedComponent(e.getX(), e.getY());

      if (clickedOn != null) {
        elist.setSelected(clickedOn);
      }

      mmc.view.displayAttributes(clickedOn);
    }
    if (e.getButton() == 3) {
      rightPressed = true;
      leftPressed = false;
    }
  }
 @Override
 public void run() {
   try {
     while (true) {
       synchronized (queue) {
         sendNow(queue);
       }
       int l = connections.size();
       for (int i = 0; i < l; i++) {
         Connection c = connections.get(i);
         if (c != null && c.ready()) {
           JsonObject message = c.read();
           if (message != null) {
             route(message, c.getNode());
           }
         }
       }
       Thread.sleep(1000L);
       // System.out.print('+');
     }
   } catch (InterruptedException e) {
     System.out.println("Closing server!");
   }
 }
  // ***************** MouseListener *****************
  public void mouseReleased(MouseEvent e) {
    currentX = getGraphCoordinateX(e.getX());
    currentY = getGraphCoordinateY(e.getY());

    MoleculeComponent clickedOn = elist.getClickedComponent(e.getX(), e.getY());

    if (drawArrowLine || drawBondLine) // if connection is being made
    {
      if (clickedOn != null && elist.getSelected() != null) // if released on valid component
      {
        if (clickedOn.getClass() == Element.class
            && (rightPressed && !leftPressed)) { // if it's a bond
          elist.add(new Bond(elist.getSelected(), clickedOn));
        } else if (clickedOn.getClass() == Element.class && (leftPressed && !rightPressed)) {
          elist.add(new Arrow(elist.getSelected(), clickedOn));
        }
      }

      drawArrowLine = false;
      drawBondLine = false;

      repaint();
    } else // connection is not being made
    {
      if (clickedOn != null) // if released on valid component
      {

      } else // Didn't click on valid component
      {
        if (leftPressed && !rightPressed) // If mouse button clicked was left
        {
          elist.add(new Element(currentX, currentY));
        }
      }
    }
  }
  @Override
  public void mouseDragged(MouseEvent e) {

    currentX = getGraphCoordinateX(e.getX());
    currentY = getGraphCoordinateY(e.getY());

    if (leftPressed && !rightPressed) // Left click is for arrows
    {

      /* If left click and drag:
       * 		1. If clicked on nothing, don't draw anything
       * 		2. If clicked on bond, draw line from bond (bond checked first because its
       * 				points aren't on the grid system)
       * 		2. If clicked on element, draw line from element
       */

      drawBondLine = false;

      if (drawArrowLine == true) {
        repaint();
        return;
      }

      MoleculeComponent component = elist.getClickedComponent(e.getX(), e.getY());

      if (component != null) {
        elist.setSelected(component);
        drawArrowLine = true;
      }

      //			Bond bArrowStart = null; //Attempt to find a bond at this point to drag from
      //			for(Bond b : elist.getBonds())
      //			{
      //				if (b.contains(e.getX(), e.getY()))
      //				{
      //					System.out.println("YES!");
      //					bArrowStart = b;
      //					break;
      //				}
      //				else
      //				{
      //					System.out.println("NO :(");
      //				}
      //			}
      //
      //			Element eArrowStart = elist.getElementAt(roundX, roundY);//Attempt to see if there is an
      // element.
      //			if(eArrowStart == null) //If there is no element at this point...
      //			{
      //				if(bArrowStart != null)//Check to see if the bond is null.
      //				{
      //					System.out.println("Did it reach here?");
      //					elist.setSelected(bArrowStart);
      //					drawArrowLine = true;
      //				}
      //			}
      //			else
      //			{
      //				elist.setSelected(elist.getElementAt(eArrowStart.getKey()));//Start the arrow here
      //				drawArrowLine = true;
      //			}

    }

    if (rightPressed && !leftPressed) // Right click is for bonding
    {
      drawArrowLine = false;
      /* Cases to consider:
       * 1. If user is already dragging (this should come first!)
       * 1. Clicked on element
       * 2. Clicked no empty grid space
       */

      if (drawBondLine == true) // if the element is already in the process of being bonded
      {
        repaint();
        return; // No need for further steps.
      }

      currentX = getGraphCoordinateX(e.getX());
      currentY = getGraphCoordinateY(e.getY());

      Element bondStart = elist.getElementAt(currentX, currentY);

      // If this is the initial movement for bonding:
      if (bondStart != null) // if bonding began at element
      {
        elist.setSelected(
            elist.getElementAt(bondStart.getKey())); // keep track of the bonding element
        drawBondLine = true; // indicate that an arrow should start to be drawn
      } else // if nothing is being dragged
      {

      }
    } // */
  }