@Before
  public void setUp() throws Exception {

    String resourceId1 = "Global Mosaic, pan sharpened visual";
    source =
        (NASASource)
            WMTSourceFactory.createSource(
                null, WMTSource.getRelatedServiceUrl(NASASource.class), resourceId1, true);

    String resourceId2 = "Continental US Elevation";
    sourceUSA =
        (NASASource)
            WMTSourceFactory.createSource(
                null, WMTSource.getRelatedServiceUrl(NASASource.class), resourceId2, true);
  }
  private Map<String, Tile> checkTooManyTiles(
      ILayer layer,
      WMTSource wmtSource,
      WMTLayerProperties layerProperties,
      WMTRenderJob renderJob,
      Map<String, Tile> tileList) {
    int tilesCount = tileList.size();

    if (tilesCount > WMTRenderJob.getTileLimitWarning()) {
      // too many tiles, let's use the recommended zoom-level (if it wasn't already used)
      Boolean selectionAutomatic = layerProperties.getSelectionAutomatic();

      if ((selectionAutomatic != null) && (selectionAutomatic == false)) {
        tileList.clear();
        tileList =
            wmtSource.cutExtentIntoTiles(
                renderJob, WMTRenderJob.getScaleFactor(), true, layerProperties);
        tilesCount = tileList.size();
      }

      // show a warning about this
      layer.setStatus(ILayer.WARNING);
      layer.setStatusMessage(Messages.Render_Warning_TooManyTiles);

      WMTPlugin.trace("[BasicWMTRender.render] Set WARNING_TOO_MANY_TILES"); // $NON-NLS-1$
    }

    if (tilesCount > WMTRenderJob.getTileLimitError()) {
      // this is just too much, cancel
      WMTPlugin.trace("[BasicWMTRender.render] Set ERROR_TOO_MANY_TILES"); // $NON-NLS-1$

      return Collections.emptyMap();
    }

    return tileList;
  }
  public void render(Graphics2D destination, Envelope bounds, IProgressMonitor monitor)
      throws RenderException {
    WMTPlugin.trace("[BasicWMTRender.render] is called"); // $NON-NLS-1$

    if (monitor == null) {
      monitor = new NullProgressMonitor();
    }
    monitor.beginTask("Render WMT", 100); // $NON-NLS-1$
    setState(STARTING);

    ILayer layer = null;
    try {
      layer = getContext().getLayer();
      // assume everything will work fine
      layer.setStatus(ILayer.DONE);
      layer.setStatusMessage(""); // $NON-NLS-1$

      WMTSource wmtSource = getWmtSourceFromLayer(layer);

      if (wmtSource == null)
        throw new UnsupportedOperationException(Messages.Render_Error_NoSource);

      // Layer properties
      WMTLayerProperties layerProperties =
          new WMTLayerProperties((StyleBlackboard) layer.getStyleBlackboard());

      // Get map extent, which should be drawn
      ReferencedEnvelope mapExtent = getRenderBounds();
      if (mapExtent == null) {
        mapExtent = context.getViewportModel().getBounds();
      }

      // Scale
      double scale = getContext().getViewportModel().getScaleDenominator();
      WMTPlugin.trace("[BasicWMTRender.render] Scale: " + scale); // $NON-NLS-1$

      WMTRenderJob renderJob = null;
      try {
        renderJob = WMTRenderJob.createRenderJob(mapExtent, scale, wmtSource);
      } catch (Exception exc) {
        throw new UnsupportedOperationException(Messages.Render_Error_Projection);
      }

      // Find tiles
      Map<String, Tile> tileList =
          wmtSource.cutExtentIntoTiles(
              renderJob, WMTRenderJob.getScaleFactor(), false, layerProperties);

      // if we have nothing to display, return
      if (tileList.isEmpty()) {
        throw new UnsupportedOperationException(Messages.Render_Error_NoData);
      }

      // check if this are too many tiles
      if ((tileList = checkTooManyTiles(layer, wmtSource, layerProperties, renderJob, tileList))
          .isEmpty()) {
        throw new UnsupportedOperationException(Messages.Render_Error_TooManyTiles);
      }

      // Download and display tiles

      // look up the preference for caching tiles on-disk or in
      // memory and use the proper tilerange for that.
      TileRange range = createTileRange(wmtSource, renderJob, tileList);

      // create an empty raster symbolizer for rendering
      RasterSymbolizer style = styleBuilder.createRasterSymbolizer();

      // setup how much each tile is worth for the monitor work %
      int tileCount = range.getTileCount();
      int tileWorth = (tileCount / 100) * tileCount;

      int thisid = 0;
      if (testing) {
        staticid++;
        thisid = staticid;
      }

      // first render any tiles that are ready and render non-ready tiles with blank images
      Map<String, Tile> tiles = range.getTiles();
      Set<String> notRenderedTiles = new HashSet<String>();
      Set<String> renderedTiles = new HashSet<String>();

      renderReadyTiles(
          destination,
          monitor,
          renderJob,
          style,
          tileWorth,
          thisid,
          tiles,
          notRenderedTiles,
          renderedTiles);

      setState(RENDERING);

      // if the tilerange is not already completed, then load
      // the missing tiles
      if (!notRenderedTiles.isEmpty()) {
        renderNotRenderedTiles(
            destination,
            monitor,
            renderJob,
            range,
            style,
            tileWorth,
            thisid,
            notRenderedTiles,
            renderedTiles);
      }

      if (testing) {
        System.out.println("DONE!!!: " + thisid); // $NON-NLS-1$
      }
    } catch (UnsupportedOperationException doneExc) {
      setDone(monitor);

      layer.setStatus(ILayer.ERROR);
      layer.setStatusMessage(doneExc.getMessage());
      WMTPlugin.log("[BasicWMTRenderer.render] Error: ", doneExc); // $NON-NLS-1$

      return;
    } catch (CancellationException cancelExc) {
      return;
    } catch (Exception ex) {
      WMTPlugin.log("[BasicWMTRenderer.render] Unexpected Error: ", ex); // $NON-NLS-1$
    }

    setDone(monitor);
  }