public ValueMap invoke(ValueMap values, OWLKnowledgeBase kb) {
    System.out.println("invoke UPnPAtomic");
    ControlPoint cp = new ControlPoint();
    Device device = cp.getProxyDevice(getUPnPDescription());
    Service service = device.getService(getUPnPService());
    Action action = service.getAction(getUPnPAction());

    ValueMap results = new ValueMap();

    MessageMapList inputMapList = getInputMap();
    ArgumentList inArguments = action.getInputArgumentList();
    for (int i = 0; i < inArguments.size(); i++) {
      Argument in = inArguments.getArgument(i);
      MessageMap mp = inputMapList.getMessageMap(in.getName());
      Parameter param = mp.getOWLSParameter();

      Object value = values.getValue(param);
      Object inputValue = value;

      System.out.println("value = " + value);
      if (mp.getTransformation() != null) {
        value = XSLTEngine.transform(value.toString(), mp.getTransformation());
        Node node = Utils.getAsNode(value.toString());
        inputValue = node.getFirstChild().getNodeValue();
        System.out.println("input value = " + value);
      }

      action.setArgumentValue(mp.getGroundingParameter().toString(), inputValue.toString());
    }

    boolean ctrlRes = action.postControlAction();
    if (ctrlRes == false) {
      UPnPStatus err = action.getControlStatus();
      throw new ExecutionException(
          err.getDescription() + " (" + Integer.toString(err.getCode()) + ")");
    }

    MessageMapList outputMapList = getOutputMap();
    ArgumentList outArguments = action.getOutputArgumentList();
    for (int i = 0; i < outArguments.size(); i++) {
      Argument out = outArguments.getArgument(i);
      MessageMap mp = outputMapList.getMessageMap(out.getName());

      if (mp == null) continue;

      Parameter param = mp.getOWLSParameter();

      Object outputValue = null;

      if (mp.getTransformation() == null) outputValue = out.getValue();
      else outputValue = XSLTEngine.transform(out.getValue().toString(), mp.getTransformation());

      // FIXME UPnP
      // results.setValue(param, outputValue);
    }

    return results;
  }
 /* (non-Javadoc)
  * @see org.mindswap.owls.grounding.AtomicGrounding#getDescriptionURL()
  */
 public URL getDescriptionURL() {
   try {
     ControlPoint cp = new ControlPoint();
     Device device = cp.getProxyDevice(getUPnPDescription());
     String url = device.getPresentationURL();
     cp.stop();
     return new URL(url);
   } catch (Exception e) {
     return null;
   }
 }