/**
   * @throws KeeperException
   * @throws InterruptedException
   * @throws NoSuchElementException
   */
  protected byte[] getNext(boolean waitForElement, boolean deleteElement)
      throws KeeperException, InterruptedException, NoSuchElementException {
    TreeMap<KEY, String> orderedChildren;

    // element, take, and remove follow the same pattern.
    // We want to return the child node with the smallest sequence number.
    // Since other clients are remove()ing and take()ing nodes concurrently,
    // the child with the smallest sequence number in orderedChildren might
    // be gone by the time we check.
    // We don't call getChildren again until we have tried the rest of the
    // nodes in sequence order,
    // BUT if the children change with a higher priority
    // than the current child we are getting, then we reload all the
    // children.

    while (true) {
      PriorityLatchChildWatcher childWatcher = new PriorityLatchChildWatcher();
      try {
        orderedChildren = orderedChildren(childWatcher);
      } catch (KeeperException.NoNodeException e) {

        if (waitForElement) {
          zookeeper.create(dir, new byte[0], acl, CreateMode.PERSISTENT);
          continue;
        } else {
          throw new NoSuchElementException();
        }
      }

      if (orderedChildren.size() == 0) {
        if (waitForElement) {
          childWatcher.awaitChange();
          continue;
        } else {
          throw new NoSuchElementException();
        }
      }

      for (String headNode : orderedChildren.values()) {
        String path = dir + "/" + headNode;
        try {
          byte[] data = zookeeper.getData(path, false, null);

          if (childWatcher.hasChangedHigherThan(keyHandler.getPriority(headNode))) {
            break;
          }

          if (deleteElement) {
            zookeeper.delete(path, -1);
          }
          return data;
        } catch (KeeperException.NoNodeException e) {
          // Another client deleted the node first.
        }
      }
    } // while loop end
  }
  /**
   * Returns a Map of the children, ordered by id.
   *
   * @param watcher optional watcher on getChildren() operation.
   * @return map from id to child name for all children
   */
  private TreeMap<KEY, String> orderedChildren(Watcher watcher)
      throws KeeperException, InterruptedException {
    TreeMap<KEY, String> orderedChildren = new TreeMap<KEY, String>();

    List<String> childNames = null;
    try {
      childNames = zookeeper.getChildren(dir, watcher);
    } catch (KeeperException.NoNodeException e) {
      throw e;
    }

    for (String childName : childNames) {
      try {

        /*
         * CHANGED FROM... if(!childName.regionMatches(0, prefix, 0,
         * prefix.length())){
         * LOGGER.warn("Found child node with improper name: " +
         * childName); continue; } String suffix =
         * childName.substring(prefix.length()); Long childId = new
         * Long(suffix);
         */

        // Check format
        if (!keyHandler.hasValidName(childName)) {
          LOGGER.warn("Found child node with improper name: " + childName);
          continue;
        }

        KEY childId = keyHandler.generateKey(childName);
        orderedChildren.put(childId, childName);
      } catch (NumberFormatException e) {
        LOGGER.warn("Found child node with improper format : " + childName + " " + e, e);
      }
    }

    return orderedChildren;
  }
  /**
   * Inserts data into queue.
   *
   * @param data
   * @return true if data was successfully added
   */
  public boolean offer(byte[] data, PRIORITY priority)
      throws KeeperException, InterruptedException {
    while (true) {
      try {

        // WAS:
        // zookeeper.create(dir+"/"+prefix, data, acl,
        // CreateMode.PERSISTENT_SEQUENTIAL);
        zookeeper.create(
            dir + "/" + keyHandler.generateChildNamePrefix(priority),
            data,
            acl,
            CreateMode.PERSISTENT_SEQUENTIAL);
        return true;
      } catch (KeeperException.NoNodeException e) {
        zookeeper.create(dir, new byte[0], acl, CreateMode.PERSISTENT);
      }
    }
  }