@Override
    public void encode(Object o) throws IllegalArgumentException {
      // register namespaces provided by extended capabilities
      NamespaceSupport namespaces = getNamespaceSupport();
      namespaces.declarePrefix("wcscrs", "http://www.opengis.net/wcs/service-extension/crs/1.0");
      namespaces.declarePrefix(
          "int", "http://www.opengis.net/WCS_service-extension_interpolation/1.0");
      namespaces.declarePrefix("gml", "http://www.opengis.net/gml/3.2");
      namespaces.declarePrefix("gmlcov", "http://www.opengis.net/gmlcov/1.0");
      namespaces.declarePrefix("swe", "http://www.opengis.net/swe/2.0");
      namespaces.declarePrefix("xlink", "http://www.w3.org/1999/xlink");
      namespaces.declarePrefix("xsi", "http://www.w3.org/2001/XMLSchema-instance");

      for (WCS20CoverageMetadataProvider cp : extensions) {
        cp.registerNamespaces(namespaces);
      }

      // is this a GridCoverage?
      if (!(o instanceof GridCoverage2D)) {
        throw new IllegalArgumentException(
            "Provided object is not a GridCoverage2D:"
                + (o != null ? o.getClass().toString() : "null"));
      }
      final GridCoverage2D gc2d = (GridCoverage2D) o;
      // we are going to use this name as an ID
      final String gcName = gc2d.getName().toString(Locale.getDefault());

      // get the crs and look for an EPSG code
      final CoordinateReferenceSystem crs = gc2d.getCoordinateReferenceSystem2D();
      List<String> axesNames =
          GMLTransformer.this.envelopeDimensionsMapper.getAxesNames(gc2d.getEnvelope2D(), true);

      // lookup EPSG code
      Integer EPSGCode = null;
      try {
        EPSGCode = CRS.lookupEpsgCode(crs, false);
      } catch (FactoryException e) {
        throw new IllegalStateException("Unable to lookup epsg code for this CRS:" + crs, e);
      }
      if (EPSGCode == null) {
        throw new IllegalStateException("Unable to lookup epsg code for this CRS:" + crs);
      }
      final String srsName = GetCoverage.SRS_STARTER + EPSGCode;
      // handle axes swap for geographic crs
      final boolean axisSwap = CRS.getAxisOrder(crs).equals(AxisOrder.EAST_NORTH);

      final AttributesImpl attributes = new AttributesImpl();
      helper.registerNamespaces(getNamespaceSupport(), attributes);

      // using Name as the ID
      attributes.addAttribute(
          "", "gml:id", "gml:id", "", gc2d.getName().toString(Locale.getDefault()));
      start("gml:RectifiedGridCoverage", attributes);

      // handle domain
      final StringBuilder builder = new StringBuilder();
      for (String axisName : axesNames) {
        builder.append(axisName).append(" ");
      }
      String axesLabel = builder.substring(0, builder.length() - 1);
      try {
        GeneralEnvelope envelope = new GeneralEnvelope(gc2d.getEnvelope());
        handleBoundedBy(envelope, axisSwap, srsName, axesLabel, null);
      } catch (IOException ex) {
        throw new WCS20Exception(ex);
      }

      // handle domain
      builder.setLength(0);
      axesNames =
          GMLTransformer.this.envelopeDimensionsMapper.getAxesNames(gc2d.getEnvelope2D(), false);
      for (String axisName : axesNames) {
        builder.append(axisName).append(" ");
      }
      axesLabel = builder.substring(0, builder.length() - 1);
      handleDomainSet(gc2d.getGridGeometry(), gc2d.getDimension(), gcName, srsName, axisSwap);

      // handle rangetype
      handleRangeType(gc2d);

      // handle coverage function
      final GridEnvelope2D ge2D = gc2d.getGridGeometry().getGridRange2D();
      handleCoverageFunction(ge2D, axisSwap);

      // handle range
      handleRange(gc2d);

      // handle metadata OPTIONAL
      try {
        handleMetadata(null, null);
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      end("gml:RectifiedGridCoverage");
    }