public void saveServiceDefinition(String serviceId) {

    Resource serviceDefFile = getServiceDefXml(serviceId, false);
    Service service = getCurrentServiceDefinition(serviceId);

    Service oldService = null;
    if (serviceId.equals(CommonConstants.SALESFORCE_SERVICE)) {
      // For salesforceService, we need to retain service definitions in
      // the old service definition file.
      oldService = loadServiceDefinition(serviceId);

      if (oldService != null) {
        for (Operation op : oldService.getOperation()) {
          if (isDeletedQuery(op)) {
            this.cfg.removeDeletedSFQueries(op.getName());
            continue;
          }
          service.addOperation(op);
        }

        List<DataObject> dataObjects = service.getDataobjects().getDataobject();
        for (DataObject dobj : oldService.getDataobjects().getDataobject()) {
          if (isDeletedSFDataObject(dobj)) {
            this.cfg.removeDeletedSFDataObjects(dobj.getName());
            continue;
          }
          dataObjects.add(dobj);
        }

        service.setType(oldService.getType());
        service.setCRUDService(oldService.getCRUDService());
      }
    } // salesforce
    try {
      Marshaller marshaller = definitionsContext.createMarshaller();
      marshaller.setProperty("jaxb.formatted.output", true);
      OutputStream outputStream = this.fileSystem.getOutputStream(serviceDefFile);
      try {
        marshaller.marshal(service, outputStream);
      } finally {
        try {
          outputStream.close();
        } catch (IOException e) {
          throw new IllegalStateException("Unable to close service def file", e);
        }
      }
      // XXX MAV-569 should do a real build here, or actually outside
      // this method maybe
      SortedSet<Service> s = new TreeSet<Service>(new ServiceComparator());
      s.add(service);
      generateRuntimeConfiguration(s);
    } catch (JAXBException e) {
      throw new WMRuntimeException(e);
    } catch (IOException e) {
      throw new WMRuntimeException(e);
    } catch (NoSuchMethodException e) {
      throw new WMRuntimeException(e);
    }
  }
  /** Return the operation for the passed name, or null if it doesn't exist. */
  public Operation getOperation(String serviceId, String name) {

    Service service = getCurrentServiceDefinition(serviceId);
    for (Operation operation : service.getOperation()) {
      if (operation.getName().equals(name)) {
        return operation;
      }
    }
    return null;
  }
  /**
   * Return a list of all operations registered with a given service.
   *
   * @param serviceId The service to examine.
   * @return
   */
  public List<String> getOperationNames(String serviceId) {

    Service service = getCurrentServiceDefinition(serviceId);
    List<Operation> operations = service.getOperation();
    List<String> ret = new ArrayList<String>(operations.size());
    for (Operation op : operations) {
      ret.add(op.getName());
    }

    return ret;
  }
 private boolean isDeletedQuery(Operation op) {
   Collection<String> deletedSFQueries = this.cfg.getDeletedSFQueries();
   for (String opn : deletedSFQueries) {
     if (op.getName().equals(opn)) {
       return true;
     }
   }
   return false;
 }
  // -----------------------------------------------------------------------
  // internal ops
  // -----------------------------------------------------------------------
  protected void doUpdateOperation(
      ServiceOperation so,
      Service service,
      ServiceDefinition sd,
      IPwsServiceModifier serviceModifier) {

    List<Operation> ops = service.getOperation();

    Operation op = null;
    for (Operation opTemp : ops) {
      if (opTemp.getName().equals(so.getName())) {
        op = opTemp;
        break;
      }
    }
    if (op == null) {
      op = new Operation();
      op.setName(so.getName());
      ops.add(op);
    }

    List<Operation.Parameter> params = op.getParameter();

    if (params.size() > 0) {
      params.clear();
    }

    for (FieldDefinition input : so.getParameterTypes()) {
      Operation.Parameter param = new Operation.Parameter();
      param.setIsList(input.getDimensions() > 0);
      param.setName(input.getName());
      if (input.getTypeDefinition() != null) {
        param.setTypeRef(input.getTypeDefinition().getTypeName());
      }
      params.add(param);
    }

    if (so.getReturnType() != null) {
      Operation.Return ret = new Operation.Return();
      FieldDefinition retType;
      if (serviceModifier == null) {
        retType = so.getReturnType();
      } else {
        retType = serviceModifier.getOperationReturnType(so);
      }

      ret.setIsList(retType.getDimensions() > 0);
      if (retType.getTypeDefinition() != null) {
        ret.setTypeRef(retType.getTypeDefinition().getTypeName());
      }
      op.setReturn(ret);

      op.setOperationType(so.getOperationType());
    }
  }