public synchronized void removeOperation(Class<?> key) {
   OperationType op = operations.remove(key.getAnnotation(Operation.class).id());
   if (op != null) {
     operations.remove(op.getId());
     lookup = null;
   }
 }
 protected Object doInvoke(OperationContext ctx, Map<String, Object> args, Object input)
     throws Exception {
   Object target = op.newInstance(ctx, args);
   if (consume == Void.TYPE) {
     // preserve last output for void methods
     Object out = method.invoke(target);
     return produce == Void.TYPE ? input : out;
   } else {
     if (input != null && !consume.isAssignableFrom(input.getClass())) {
       // try to adapt
       input = op.getService().getAdaptedValue(ctx, input, consume);
     }
     return method.invoke(target, input);
   }
 }
 public Object invoke(OperationContext ctx, Map<String, Object> args) throws OperationException {
   try {
     return doInvoke(ctx, args, ctx.getInput());
   } catch (OperationException e) {
     throw e;
   } catch (InvocationTargetException e) {
     Throwable t = e.getTargetException();
     if (t instanceof OperationException) {
       throw (OperationException) t;
     } else {
       throw new OperationException("Failed to invoke operation " + op.getId(), t);
     }
   } catch (Throwable t) {
     throw new OperationException("Failed to invoke operation " + op.getId(), t);
   }
 }
 /** Return 0 for no match. */
 public int inputMatch(Class<?> in) {
   if (consume == in) {
     return priority > 0 ? priority : EXACT_MATCH_PRIORITY;
   }
   if (consume.isAssignableFrom(in)) {
     return priority > 0 ? priority : ISTANCE_OF_PRIORITY;
   }
   if (op.getService().isTypeAdaptable(in, consume)) {
     return priority > 0 ? priority : ADAPTABLE_PRIORITY;
   }
   if (consume == Void.TYPE) {
     return priority > 0 ? priority : VOID_PRIORITY;
   }
   return 0;
 }