class UserMaximumExtentCommand implements CommandHasRequest<UserMaximumExtentRequest, UserMaximumExtentResponse> {

	@Override
	public void execute(UserMaximumExtentRequest request, UserMaximumExtentResponse response) throws Exception {
		String[] layers;
		ArrayList<String> tempLayers = new ArrayList<String>();
		String[] includeLayers = request.getLayerIds();
		boolean excludeRasterLayers = request.isExcludeRasterLayers();
		if (includeLayers != null && includeLayers.length > 0) {
			for (String layerId : includeLayers) {
				if (!securityContext.isLayerVisible(layerId)) {
					throw new GeomajasSecurityException(ExceptionCode.LAYER_NOT_VISIBLE, layerId);
				}
				Layer<?> l = configurationService.getLayer(layerId);
				if (null == l) {
					throw new GeomajasException(ExceptionCode.LAYER_NOT_FOUND, layerId);
				}
				if (!excludeRasterLayers || l.getLayerInfo().getLayerType() != LayerType.RASTER) {
					tempLayers.add(l.getId());
				}
			}
		}
		layers = tempLayers.toArray(new String[tempLayers.size()]);

		Layer<?> layer;
		Crs targetCrs = geoService.getCrs2(request.getCrs());

		if (layers.length == 0) {
			// return empty bbox
			response.setBounds(new Bbox());
		} else {
			Envelope extent = new Envelope();
			for (String layerId : layers) {
				layer = configurationService.getLayer(layerId);
				if (layer != null) {
					Envelope bounds;
					if (layer.getLayerInfo().getLayerType() == LayerType.RASTER) {
						bounds = securityContext.getVisibleArea(layerId).getEnvelopeInternal();
						CrsTransform transform = geoService.getCrsTransform(layer.getCrs(), targetCrs);
						bounds = geoService.transform(bounds, transform);
					} else {
						bounds = layerService.getBounds(layerId, targetCrs, null);
					}
					extent.expandToInclude(bounds);
				} else {
					log.warn("layer not found ?! " + layerId);
				}
			}
			response.setBounds(converterService.toDto(extent));
		}
	}

}