public WPSCapabilitiesType run(GetCapabilitiesType request) throws WPSException {
    // do the version negotiation dance
    List<String> provided = Collections.singletonList("1.0.0");
    List<String> accepted = null;
    if (request.getAcceptVersions() != null) accepted = request.getAcceptVersions().getVersion();
    String version = RequestUtils.getVersionOws11(provided, accepted);

    if (!"1.0.0".equals(version)) {
      throw new WPSException("Could not understand version:" + version);
    }

    // TODO: add update sequence negotiation

    // encode the response
    Wps10Factory wpsf = Wps10Factory.eINSTANCE;
    Ows11Factory owsf = Ows11Factory.eINSTANCE;

    WPSCapabilitiesType caps = wpsf.createWPSCapabilitiesType();
    caps.setVersion("1.0.0");

    // TODO: make configurable
    caps.setLang("en");

    // ServiceIdentification
    ServiceIdentificationType si = owsf.createServiceIdentificationType();
    caps.setServiceIdentification(si);

    si.getTitle().add(Ows11Util.languageString(wps.getTitle()));
    si.getAbstract().add(Ows11Util.languageString(wps.getAbstract()));

    KeywordsType kw = Ows11Util.keywords(wps.keywordValues());
    ;
    if (kw != null) {
      si.getKeywords().add(kw);
    }

    si.setServiceType(Ows11Util.code("WPS"));
    si.getServiceTypeVersion().add("1.0.0");
    si.setFees(wps.getFees());

    if (wps.getAccessConstraints() != null) {
      si.getAccessConstraints().add(wps.getAccessConstraints());
    }

    // ServiceProvider
    ServiceProviderType sp = owsf.createServiceProviderType();
    caps.setServiceProvider(sp);

    // TODO: set provder name from context
    GeoServerInfo geoServer = wps.getGeoServer().getGlobal();
    if (geoServer.getContact().getContactOrganization() != null) {
      sp.setProviderName(geoServer.getContact().getContactOrganization());
    } else {
      sp.setProviderName("GeoServer");
    }

    sp.setProviderSite(owsf.createOnlineResourceType());
    sp.getProviderSite().setHref(geoServer.getOnlineResource());
    sp.setServiceContact(responsibleParty(geoServer, owsf));

    // OperationsMetadata
    OperationsMetadataType om = owsf.createOperationsMetadataType();
    caps.setOperationsMetadata(om);

    OperationType gco = owsf.createOperationType();
    gco.setName("GetCapabilities");
    gco.getDCP().add(Ows11Util.dcp("wps", request));
    om.getOperation().add(gco);

    OperationType dpo = owsf.createOperationType();
    dpo.setName("DescribeProcess");
    dpo.getDCP().add(Ows11Util.dcp("wps", request));
    om.getOperation().add(dpo);

    OperationType eo = owsf.createOperationType();
    eo.setName("Execute");
    eo.getDCP().add(Ows11Util.dcp("wps", request));
    om.getOperation().add(eo);

    ProcessOfferingsType po = wpsf.createProcessOfferingsType();
    caps.setProcessOfferings(po);

    // gather the process list
    for (ProcessFactory pf : Processors.getProcessFactories()) {
      for (Name name : pf.getNames()) {
        if (!getProcessBlacklist().contains(name)) {
          ProcessBriefType p = wpsf.createProcessBriefType();
          p.setProcessVersion(pf.getVersion(name));
          po.getProcess().add(p);

          p.setIdentifier(Ows11Util.code(name));
          p.setTitle(Ows11Util.languageString(pf.getTitle(name)));
          p.setAbstract(Ows11Util.languageString(pf.getDescription(name)));
        }
      }
    }
    // sort it
    ECollections.sort(
        po.getProcess(),
        new Comparator() {

          public int compare(Object o1, Object o2) {
            ProcessBriefType pb1 = (ProcessBriefType) o1;
            ProcessBriefType pb2 = (ProcessBriefType) o2;

            final String id1 = pb1.getIdentifier().getValue();
            final String id2 = pb2.getIdentifier().getValue();
            return id1.compareTo(id2);
          }
        });

    LanguagesType1 languages = wpsf.createLanguagesType1();
    caps.setLanguages(languages);

    DefaultType2 defaultLanguage = wpsf.createDefaultType2();
    languages.setDefault(defaultLanguage);
    defaultLanguage.setLanguage("en-US");

    LanguagesType supportedLanguages = wpsf.createLanguagesType();
    languages.setSupported(supportedLanguages);
    supportedLanguages.getLanguage().add("en-US");

    return caps;
    // Version detection and alternative invocation if being implemented.
  }
  void assertOperationsMetadata(WFSCapabilitiesType caps) {
    OperationsMetadataType om = caps.getOperationsMetadata();
    assertNotNull(om);

    // assertEquals(6, om.getOperation().size());

    OperationType getCapsOp = (OperationType) om.getOperation().get(0);
    assertEquals("GetCapabilities", getCapsOp.getName());
    assertEquals(1, getCapsOp.getDCP().size());

    DCPType dcp1 = (DCPType) getCapsOp.getDCP().get(0);
    assertEquals(1, dcp1.getHTTP().getGet().size());
    assertEquals(1, dcp1.getHTTP().getPost().size());

    assertEquals(
        "http://localhost:8080/geoserver/wfs?get",
        ((RequestMethodType) dcp1.getHTTP().getGet().get(0)).getHref());
    assertEquals(
        "http://localhost:8080/geoserver/wfs?post",
        ((RequestMethodType) dcp1.getHTTP().getPost().get(0)).getHref());

    int i = 1;
    assertEquals("DescribeFeatureType", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("GetFeature", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("GetPropertyValue", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("ListStoredQueries", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("DescribeStoredQueries", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("CreateStoredQuery", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("DropStoredQuery", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("LockFeature", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("GetFeatureWithLock", ((OperationType) om.getOperation().get(i++)).getName());
    assertEquals("Transaction", ((OperationType) om.getOperation().get(i++)).getName());
  }