/**
   * This method returns a list of urls for retrieving the individual layers of the map. It will
   * coalesce adjacent layers into a single request, when possible.
   *
   * @param layerList Element parent node to the list of layer Elements within the ViewContext
   * @param layers String[] of layer names
   * @param bbox Envelope spatial extent of the map image
   * @param width x-dimension of the map image
   * @param height y-dimension of the map image
   * @param format String mime-type of the map image
   * @return List of urls for get map requests
   * @ssdd
   */
  private List<String> getLayerRequests(
      Element layerList, String[] layers, Envelope bbox, int width, int height, String format) {

    List<String> requests = new ArrayList<String>();
    String lastServer = null;

    for (Element elem : DOMUtils.getChildren(layerList, "Layer")) {
      // get layer name
      String name = DOMUtils.getChildText(elem, "Name");
      // is layer in list of requested layers?
      if (!contains(layers, name)) continue;
      // is layer visible?
      if (Coerce.toBoolean(elem.getAttribute("hidden"))) continue;
      // get href to layer's service
      Node server = DOMUtils.getChild(elem, "Server");
      Element or = DOMUtils.getChild(server, "OnlineResource");
      String href = or.getAttribute("xlink:href");

      if (href.equals(lastServer)) {
        String layerNames = requests.remove(requests.size() - 1);
        layerNames += "," + name;
        requests.add(layerNames);
      } else {
        lastServer = href;
        requests.add(getMapRequest(href, name, bbox, width, height, format));
      }
    }
    return requests;
  }
  /**
   * This method renders the <code>layers</code> from the <code>viewContext</code> into an image of
   * the specified <code>width</code> and <code>height</code> contrained by the <code>bbox</code>.
   *
   * @param viewContext Node root node in ViewContext document
   * @param bbox Envelope spatial extent of map
   * @param width int x-dimension of map image
   * @param height int y-dimension of map image
   * @param format String mimetype of resulting map image and propogated to the map services
   *     providing each component layer.
   * @return Image composited map image
   * @throws Exception
   * @ssdd
   */
  public Image render(
      Element viewContext, String[] layers, Envelope bbox, int width, int height, String format)
      throws Exception {

    String formatType = format.substring(format.indexOf("/") + 1, format.length());
    BufferedImage image = createImage(formatType, width, height, true);

    Dimension2D window = new Dimension(width, height);
    Graphics2D graphics = (Graphics2D) image.getGraphics();
    AffineTransform t = ProjectionUtility.total(window, bbox);
    graphics.setTransform(t);

    graphics.setColor(BACKGROUND_COLOR);

    Element layerList = DOMUtils.getChild(viewContext, "LayerList");
    List<String> requests = getLayerRequests(layerList, layers, bbox, width, height, format);
    for (String url : requests) {
      fetchImage(url, graphics); // retrieve map image
      image.flush();
    }

    return image;
  }