@SuppressWarnings("unchecked")
  private void setFilter(WebMapServer wms, GetMapRequest request) {
    Filter mapFilter = null;

    Map<ILayer, Filter> filters = new HashMap<ILayer, Filter>();
    List<ILayer> layers = getContext().getLayers();
    for (ILayer layer : layers) {
      Object layerFilter =
          layer.getStyleBlackboard().get(ProjectBlackboardConstants.LAYER__DATA_QUERY);
      Filter filter;
      if (layerFilter instanceof Query) {
        filter = (Filter) ((Query) layerFilter).getFilter();
      } else if (layerFilter instanceof Filter) {
        filter = (Filter) layerFilter;
      } else {
        filter = mapFilter;
      }
      if (filter != null && filter != Filter.INCLUDE) {
        filters.put(layer, filter);
      }
    }

    if (filters.isEmpty()) return;

    StringBuilder builder = new StringBuilder();
    HashMap hashMap = new HashMap();
    for (Map.Entry<ILayer, Filter> entry : filters.entrySet()) {
      if (entry.getValue() == null) builder.append('(');
      try {
        StringWriter writer = new StringWriter();
        DocumentWriter.writeDocument(entry.getValue(), FilterSchema.getInstance(), writer, hashMap);
        builder.append(writer.toString());
      } catch (OperationNotSupportedException e) {
        WMSPlugin.log(
            "Error writing filter for layer: " + entry.getKey().getID(), e); // $NON-NLS-1$
        builder.append("<Filter/>"); // $NON-NLS-1$
      } catch (IOException e) {
        // SHOULDN'T Happen I don't think...
        assert false;
        WMSPlugin.log(
            "Error writing filter for layer: " + entry.getKey().getID(), e); // $NON-NLS-1$
        builder.append("<Filter/>"); // $NON-NLS-1$
      }
      builder.append(')');
    }

    try {
      String encode = URLEncoder.encode(builder.toString(), "UTF-8"); // $NON-NLS-1$
      request.setVendorSpecificParameter("filter", encode); // $NON-NLS-1$
    } catch (UnsupportedEncodingException e) {
      // better not happen!
      throw (RuntimeException) new RuntimeException().initCause(e);
    }
  }
  /**
   * Using the viewport bounds and combined wms layer extents, determines an appropriate bounding
   * box by projecting the viewport into the request CRS, intersecting the bounds, and returning the
   * result.
   *
   * @param wmsLayers all adjacent wms layers we are requesting
   * @param viewport map editor bounds and crs
   * @param requestCRS coordinate reference system supported by the server
   * @return the bbox to ask the server for
   * @throws MismatchedDimensionException
   * @throws TransformException
   * @throws FactoryException
   */
  public static ReferencedEnvelope calculateRequestBBox(
      List<Layer> wmsLayers,
      ReferencedEnvelope viewport,
      CoordinateReferenceSystem requestCRS,
      String version)
      throws MismatchedDimensionException, TransformException, FactoryException {
    /* The bounds of all wms layers on this server combined */
    ReferencedEnvelope layersBBox = getLayersBoundingBox(requestCRS, wmsLayers, version);
    if (isEnvelopeNull(layersBBox)) {
      // the wms server has no bounds
      WMSPlugin.log("Zero width/height envelope: wmsLayers = " + layersBBox); // $NON-NLS-1$
      layersBBox = null;
      // alternatively, we could impose a reprojected -180,180,-90,90
    }

    /* The viewport bounds projected to the request crs */
    ReferencedEnvelope reprojectedViewportBBox = viewport.transform(requestCRS, true);
    if (isEnvelopeNull(reprojectedViewportBBox)) {
      // viewport couldn't be reprojected
      WMSPlugin.log(
          "Zero width/height envelope: reprojected viewport from "
              + viewport //$NON-NLS-1$
              + " to "
              + requestCRS
              + " returned "
              + reprojectedViewportBBox); //$NON-NLS-1$ //$NON-NLS-2$
    }
    // alternative for better accuracy: new ReferencedEnvelope(JTS.transform(viewport, null,
    // CRS.findMathTransform(viewportCRS, crs, true), 4), crs);

    /* The intersection of the viewport and the combined wms layers */
    Envelope interestBBox;
    if (layersBBox == null) {
      interestBBox = reprojectedViewportBBox;
    } else {
      interestBBox = reprojectedViewportBBox.intersection(layersBBox);
    }
    if (isEnvelopeNull(interestBBox)) {
      // outside of bounds, do not draw
      WMSPlugin.trace(
          "Bounds of the data are outside the bounds of the viewscreen."); //$NON-NLS-1$
      return NILL_BOX;
    }

    /* The bounds of the request we are going to make */
    ReferencedEnvelope requestBBox = new ReferencedEnvelope(interestBBox, requestCRS);
    return requestBBox;
  }
  /** Construct a new BasicWMSRenderer */
  public BasicWMSRenderer2() {
    ClassLoader current = Thread.currentThread().getContextClassLoader();
    try {
      Thread.currentThread().setContextClassLoader(WebMapServer.class.getClassLoader());
      Logger logger = Logger.getLogger("org.geotools.data.ows"); // $NON-NLS-1$
      if (WMSPlugin.isDebugging(Trace.RENDER)) {
        logger.setLevel(Level.FINE);
        logger.addHandler(
            new Handler() {

              @Override
              public void publish(LogRecord record) {
                System.err.println(record.getMessage());
              }

              @Override
              public void flush() {
                System.err.flush();
              }

              @Override
              public void close() throws SecurityException {}
            });
      } else {
        logger.setLevel(Level.SEVERE);
      }
    } finally {
      Thread.currentThread().setContextClassLoader(current);
    }
  }
 @Override
 protected IStatus run(IProgressMonitor monitor) {
   getContext().clearImage();
   try {
     render(getContext().getImage().createGraphics(), monitor);
   } catch (Throwable e) {
     WMSPlugin.log(e.getLocalizedMessage(), e);
   }
   return Status.OK_STATUS;
 }
  /**
   * We have made this visible so that WMSDescribeLayer (used by InfoView2) can figure out how to
   * make the *exact* same request in order to a getInfo operation. We should really store the last
   * request on the layer blackboard for this intra module communication.
   *
   * @return SRS code
   */
  public static String findRequestCRS(
      List<Layer> layers, CoordinateReferenceSystem viewportCRS, IMap map) {
    String requestCRS = null;

    if (layers == null || layers.isEmpty()) {
      return null;
    }

    Collection<String> viewportEPSG = extractEPSG(map, viewportCRS);
    if (viewportEPSG != null) {
      String match = matchEPSG(layers, viewportEPSG);
      if (match != null) return match;
    }

    if (matchEPSG(layers, EPSG_4326)) return EPSG_4326;

    if (matchEPSG(layers, EPSG_4269)) {
      return EPSG_4269;
    }

    Layer firstLayer = layers.get(0);
    for (Object object : firstLayer.getSrs()) {
      String epsgCode = (String) object;

      try {
        // Check to see if *we* can actually use this code first.
        CRS.decode(epsgCode);
      } catch (NoSuchAuthorityCodeException e) {
        continue;
      } catch (FactoryException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      if (matchEPSG(layers, epsgCode)) {
        requestCRS = epsgCode;
        return requestCRS;
      }
    }

    if (requestCRS == null) {
      // Hmm. Our layers have no SRS in common - we are in an illegal state
      WMSPlugin.log(
          "ERROR: Illegal State: Basic WMS Renderer contains layers with no common CRS. Unable to perform request."); //$NON-NLS-1$
      return null;
    }
    return requestCRS;
  }
  private List<ILayer> getLayers() {
    List<ILayer> layers = new ArrayList<ILayer>();

    ICompositeRenderContext context1 = getContext();
    IRenderContext[] contexts =
        context1.getContexts().toArray(new IRenderContext[context1.getContexts().size()]);

    if (contexts.length == 0)
      throw new RuntimeException(Messages.BasicWMSRenderer2_no_layers_to_render);

    for (IRenderContext renderContext : contexts) {
      if (renderContext.getLayer().isVisible()) {
        layers.add(renderContext.getLayer());
      }
    }

    if (layers.isEmpty()) {
      WMSPlugin.log("WARNING: WMS Renderer contains no layers."); // $NON-NLS-1$
    }

    return layers;
  }
  /**
   * Determines the dimensions of the image to request, usually 1:1 to display, but sometimes more
   * (too fuzzy) or less (image too large) when reprojecting.
   *
   * @param maxDimensions TODO
   * @param viewport
   * @param request
   * @param context
   * @return
   * @throws RenderException
   */
  public static Dimension calculateImageDimensions(
      Dimension displaySize, Dimension maxDimensions, Envelope viewport, Envelope request)
      throws RenderException {
    double xScale = request.getWidth() / viewport.getWidth();
    double yScale = request.getHeight() / viewport.getHeight();
    // TODO: adjust height and width when we are reprojecting to make things less fuzzy

    int width = (int) (xScale * displaySize.getWidth());
    int height = (int) (yScale * displaySize.getHeight());

    // ensure we don't exceed the dimensions the server will allow
    int maxWidth = (int) maxDimensions.getWidth();
    if ((maxWidth > 0) && (width > maxWidth)) {
      width = maxWidth;
    }
    int maxHeight = (int) maxDimensions.getHeight();
    if ((maxHeight > 0) && (height > maxHeight)) {
      height = maxHeight;
    }

    WMSPlugin.trace(
        "WMS request image dimensions: " + width + ", " + height); // $NON-NLS-1$ //$NON-NLS-2$
    return new Dimension(width, height);
  }
 private IPreferenceStore getPreferencesStore() {
   return WMSPlugin.getDefault().getPreferenceStore();
 }
  public synchronized void render(
      Graphics2D destination, ReferencedEnvelope bounds, IProgressMonitor monitor)
      throws RenderException {

    int endLayerStatus = ILayer.DONE;
    try {
      if (bounds == null || bounds.isNull()) {
        bounds = getContext().getImageBounds();
      }

      if (monitor.isCanceled()) return;

      getContext().setStatus(ILayer.WAIT);

      WebMapServer wms = getWMS();

      GetMapRequest request = wms.createGetMapRequest();

      // put in default exception format we understand as a client
      // (if suppoted by the server)
      WMSCapabilities capabilities = wms.getCapabilities();
      if (capabilities
          .getRequest()
          .getGetMap()
          .getFormats()
          .contains(GetMapRequest.EXCEPTION_XML)) {
        request.setExceptions(GetMapRequest.EXCEPTION_XML);
      }
      setImageFormat(wms, request);

      if (monitor.isCanceled()) return;

      double currScale = getContext().getViewportModel().getScaleDenominator();
      List<ILayer> layers = getLayers();
      for (int i = layers.size() - 1; i >= 0; i--) {
        ILayer ilayer = layers.get(i);
        Layer layer;
        double minScale = 0;
        double maxScale = Double.MAX_VALUE;
        layer = ilayer.getResource(org.geotools.data.ows.Layer.class, null);
        // check if there are min/max scale rules
        StyleBlackboard sb = (StyleBlackboard) ilayer.getStyleBlackboard();
        Style style = (Style) sb.lookup(Style.class);
        if (style != null) {
          Rule rule = style.getFeatureTypeStyles()[0].getRules()[0];
          minScale = rule.getMinScaleDenominator();
          maxScale = rule.getMaxScaleDenominator();
        }

        if (currScale >= minScale && currScale <= maxScale) {
          // check for a wms style
          StyleImpl wmsStyle =
              (StyleImpl) ilayer.getStyleBlackboard().get(WMSStyleContent.WMSSTYLE);
          if (wmsStyle != null) {
            request.addLayer(layer, wmsStyle);
          } else {
            request.addLayer(layer);
          }
        }
      }

      if (monitor.isCanceled()) return;

      List<Layer> wmsLayers = getWMSLayers();
      if (wmsLayers == null || wmsLayers.isEmpty()) {
        endLayerStatus = ILayer.WARNING;
        return;
      }

      // figure out request CRS
      String requestCRScode = findRequestCRS(wmsLayers, getViewportCRS(), getContext().getMap());
      // TODO: make findRequestCRS more efficient (we are running CRS.decode at *least* twice)
      CoordinateReferenceSystem requestCRS = CRS.decode(requestCRScode);

      // figure out viewport
      //            ReferencedEnvelope viewport;
      //            Envelope viewportBBox = getViewportBBox();
      //            CoordinateReferenceSystem viewportCRS = getViewportCRS();
      //            if (viewportBBox == null) {
      //                // change viewport to world
      //                viewportBBox = new Envelope(-180, 180, -90, 90);
      //                if (!DefaultGeographicCRS.WGS84.equals(viewportCRS)) { // reproject
      //                    viewport = new ReferencedEnvelope(viewportBBox,
      // DefaultGeographicCRS.WGS84);
      //                    viewportBBox = viewport.transform(viewportCRS, true);
      //                }
      //            }

      ReferencedEnvelope requestBBox = null;
      Envelope backprojectedBBox = null; // request bbox projected to the viewport crs
      //            viewport = new ReferencedEnvelope(viewportBBox, viewportCRS);
      //            requestBBox = calculateRequestBBox(wmsLayers, viewport, requestCRS);

      requestBBox = calculateRequestBBox(wmsLayers, bounds, requestCRS, capabilities.getVersion());

      // check that a request is needed (not out of a bounds, invalid, etc)
      if (requestBBox == NILL_BOX) {
        endLayerStatus = ILayer.WARNING;
        return;
      }
      assert requestBBox.getCoordinateReferenceSystem().equals(requestCRS);

      if (requestBBox.getCoordinateReferenceSystem().equals(getViewportCRS())) {
        backprojectedBBox = (Envelope) requestBBox;
      } else {
        backprojectedBBox = (Envelope) requestBBox.transform(getViewportCRS(), true);
      }

      if (WMSPlugin.isDebugging(Trace.RENDER)) {
        WMSPlugin.trace("Viewport CRS: " + getViewportCRS().getName()); // $NON-NLS-1$
        WMSPlugin.trace("Request CRS: " + requestCRS.getName()); // $NON-NLS-1$
        WMSPlugin.trace("Context Image bounds: " + getContext().getImageBounds()); // $NON-NLS-1$
        WMSPlugin.trace("Request BBox  bounds: " + requestBBox); // $NON-NLS-1$
        WMSPlugin.trace("Backprojected request bounds: " + backprojectedBBox); // $NON-NLS-1$
      }

      Service wmsService = capabilities.getService();
      Dimension maxDimensions = new Dimension(wmsService.getMaxWidth(), wmsService.getMaxHeight());
      //            Dimension imageDimensions =
      // calculateImageDimensions(getContext().getMapDisplay()
      //                    .getDisplaySize(), maxDimensions, getViewportBBox(), backprojectedBBox);
      Dimension imageDimensions =
          calculateImageDimensions(
              getContext().getImageSize(), maxDimensions, bounds, backprojectedBBox);
      if (imageDimensions.height < 1 || imageDimensions.width < 1) {
        endLayerStatus = ILayer.WARNING;
        return;
      }
      request.setDimensions(
          imageDimensions.width + "", imageDimensions.height + ""); // $NON-NLS-1$ //$NON-NLS-2$
      // epsg could be under identifiers or authority.
      Set<ReferenceIdentifier> identifiers = requestCRS.getIdentifiers();
      String srs = identifiers.isEmpty() ? EPSG_4326 : identifiers.iterator().next().toString();
      request.setSRS(srs); // EPSG_4326
      request.setBBox(requestBBox);
      // request.setBBox(requestBBox.getMinX() + "," + requestBBox.getMinY()+ "," +
      // requestBBox.getMaxX()+ "," + requestBBox.getMaxY());

      if (monitor.isCanceled()) return;

      setFilter(wms, request);

      // request.setProperty("DACS_ACS", null);
      BufferedImage image = readImage(wms, request, monitor);

      if (monitor.isCanceled()) return;

      if (image == null) {
        Exception e = new RuntimeException(Messages.BasicWMSRenderer2_unable_to_decode_image);
        throw wrapException(e);
      }

      // backprojectedBBox or viewportBBox
      renderGridCoverage(destination, backprojectedBBox, imageDimensions, requestBBox, image);

    } catch (Exception e) {
      if (e instanceof RenderException) throw (RenderException) e;
      throw new RenderException(e);
    } finally {
      getContext().setStatus(endLayerStatus);
      if (endLayerStatus == ILayer.DONE) {
        // clear the status message (rendering was successful)
        getContext().setStatusMessage(null);
      }
    }
  }
 public BasicWMSRendererPreferencePage() {
   super(GRID);
   setPreferenceStore(WMSPlugin.getDefault().getPreferenceStore());
   setDescription(Messages.BasicWMSRendererPreferencePage_warning);
 }
  public boolean canAddLayer(ILayer layer) {

    if (!layer.hasResource(Layer.class)) return false;

    try {
      if (!layer
          .findGeoResource(Layer.class)
          .parent(ProgressManager.instance().get())
          .equals(getRenderContext().getGeoResource().parent(ProgressManager.instance().get())))
        return false;
    } catch (IOException e2) {
      return false;
    }

    double opacity = Double.NaN;

    ICompositeRenderContext context1 = (ICompositeRenderContext) context;

    IRenderContext[] contexts =
        context1.getContexts().toArray(new IRenderContext[context1.getContexts().size()]);
    Arrays.sort(contexts);
    List<Layer> owsLayers = new ArrayList<Layer>();
    IService currentService;
    try {
      owsLayers.add(layer.getResource(Layer.class, new NullProgressMonitor()));
      currentService = layer.getResource(IService.class, null);
    } catch (IOException e1) {
      WMSPlugin.log("", e1); // $NON-NLS-1$
      return false;
    }
    for (IRenderContext renderContext : contexts) {
      ILayer previousLayer = renderContext.getLayer();

      try {
        owsLayers.add(previousLayer.getResource(Layer.class, new NullProgressMonitor()));
        IService previousService = previousLayer.getResource(IService.class, null);
        if (currentService != previousService) {
          return false;
        }
      } catch (IOException e) {
        WMSPlugin.log("Error while retrieving service.", e); // $NON-NLS-1$
        return false;
      }

      if (BasicWMSRenderer2.findRequestCRS(owsLayers, context.getCRS(), context.getMap()) == null)
        return false;

      Style style = (Style) previousLayer.getStyleBlackboard().get(SLDContent.ID);
      if (style != null) {
        opacity = SLDs.rasterOpacity(SLDs.rasterSymbolizer(style));
      }
    }

    Style style = (Style) layer.getStyleBlackboard().get(SLDContent.ID);
    if (style == null && Double.isNaN(opacity)) {
      return true;
    }

    double result = SLDs.rasterOpacity(SLDs.rasterSymbolizer(style));

    if (result == opacity) {
      return true;
    }
    return false;
  }