/**
   * {@inheritDoc} Adds the service to the ServiceRegistry via the ServiceRegistryManager.
   *
   * @see
   *     org.springframework.web.servlet.mvc.SimpleFormController#onSubmit(javax.servlet.http.HttpServletRequest,
   *     javax.servlet.http.HttpServletResponse, java.lang.Object,
   *     org.springframework.validation.BindException)
   */
  @Override
  protected ModelAndView onSubmit(
      final HttpServletRequest request,
      final HttpServletResponse response,
      final Object command,
      final BindException errors)
      throws Exception {
    RegisteredService service = (RegisteredService) command;

    // only change object class if there isn't an explicit RegisteredService class set
    if (this.getCommandClass() == null) {
      // CAS-1071
      // Treat _new_ patterns starting with ^ character as a regular expression
      if (service.getId() == RegisteredService.INITIAL_IDENTIFIER_VALUE
          && service.getServiceId().startsWith("^")) {
        logger.debug("Detected regular expression starting with ^");
        final RegexRegisteredService regexService = new RegexRegisteredService();
        regexService.copyFrom(service);
        service = regexService;
      }
    }
    this.servicesManager.save(service);
    logger.info("Saved changes to service " + service.getId());

    final ModelAndView modelAndView =
        new ModelAndView(new RedirectView("manage.html#" + service.getId(), true));
    modelAndView.addObject("action", "add");
    modelAndView.addObject("id", service.getId());

    return modelAndView;
  }
  @Override
  protected Object formBackingObject(final HttpServletRequest request) throws Exception {
    final String id = request.getParameter("id");

    if (!StringUtils.hasText(id)) {
      // create a default RegisteredServiceImpl object if an explicit class isn't set
      final Object service;
      if (this.getCommandClass() != null) {
        service = this.createCommand();
      } else {
        service = new RegisteredServiceImpl();
      }
      logger.debug("Created new service of type " + service.getClass().getName());
      return service;
    }

    final RegisteredService service = this.servicesManager.findServiceBy(Long.parseLong(id));

    if (service != null) {
      logger.debug("Loaded service " + service.getServiceId());
    } else {
      logger.debug("Invalid service id specified.");
    }

    return service;
  }
  public CasShibRegisteredService findServiceById(String serviceId)
      throws CasShibServiceRegistrarException {
    if (!isInitialized) {
      // this shouldn't happen here, but just in case
      initialize();
    }

    for (RegisteredService entry : servicesManager.getAllServices()) {
      if (entry instanceof CasShibRegisteredService && entry.getServiceId().equals(serviceId)) {
        return ((CasShibRegisteredService) entry);
      }
    }

    return null;
  }
  /**
   * Determines the principal id to use for a {@link RegisteredService} using the following rules:
   *
   * <ul>
   *   <li>If the service is marked to allow anonymous access, a persistent id is returned.
   *   <li>If the {@link org.jasig.cas.services.RegisteredService#getUsernameAttribute()} is blank,
   *       then the default principal id is returned.
   *   <li>If the username attribute is available as part of the principal's attributes, the
   *       corresponding attribute value will be returned.
   *   <li>Otherwise, the default principal's id is returned as the username attribute with an
   *       additional warning.
   * </ul>
   *
   * @param principal The principal object to be validated and constructed
   * @param registeredService Requesting service for which a principal is being validated.
   * @param serviceTicket An instance of the service ticket used for validation
   * @return The principal id to use for the requesting registered service
   */
  private String determinePrincipalIdForRegisteredService(
      final Principal principal,
      final RegisteredService registeredService,
      final ServiceTicket serviceTicket) {
    String principalId = null;
    final String serviceUsernameAttribute = registeredService.getUsernameAttribute();

    if (registeredService.isAnonymousAccess()) {
      principalId = this.persistentIdGenerator.generate(principal, serviceTicket.getService());
    } else if (StringUtils.isBlank(serviceUsernameAttribute)) {
      principalId = principal.getId();
    } else {
      if (principal.getAttributes().containsKey(serviceUsernameAttribute)) {
        principalId = principal.getAttributes().get(serviceUsernameAttribute).toString();
      } else {
        principalId = principal.getId();
        final Object[] errorLogParameters =
            new Object[] {
              principalId,
              registeredService.getUsernameAttribute(),
              principal.getAttributes(),
              registeredService.getServiceId(),
              principalId
            };
        logger.warn(
            "Principal [{}] did not have attribute [{}] among attributes [{}] so CAS cannot "
                + "provide on the validation response the user attribute the registered service [{}] expects. "
                + "CAS will instead return the default username attribute [{}]",
            errorLogParameters);
      }
    }

    logger.debug(
        "Principal id to return for service [{}] is [{}]. The default principal id is [{}].",
        new Object[] {registeredService.getName(), principal.getId(), principalId});
    return principalId;
  }