Ejemplo n.º 1
0
 @SuppressWarnings("rawtypes")
 @Override
 public Response toResponse(javax.validation.ValidationException exception) {
   Response.Status errorStatus = Response.Status.INTERNAL_SERVER_ERROR;
   List<String> errorsList = new ArrayList<String>();
   if (exception instanceof ConstraintViolationException) {
     ConstraintViolationException constraint = (ConstraintViolationException) exception;
     Iterator i$ = constraint.getConstraintViolations().iterator();
     while (i$.hasNext()) {
       ConstraintViolation violation = (ConstraintViolation) i$.next();
       String errorMessage = this.getPropertyName(violation) + ": " + violation.getMessage();
       errorsList.add(errorMessage);
       LOG.error(
           violation.getRootBeanClass().getSimpleName()
               + "."
               + violation.getPropertyPath()
               + ": "
               + violation.getMessage());
     }
     if (!(constraint instanceof ResponseConstraintViolationException)) {
       errorStatus = Response.Status.BAD_REQUEST;
     }
   }
   String errorsAsString = StringUtils.join(errorsList, ", ");
   Response response = Response.status(errorStatus).entity(errorsAsString).build();
   return response;
 }
Ejemplo n.º 2
0
  @POST
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  public Response importVine(Vine vine) {
    Response.ResponseBuilder builder = null;

    try {
      // Verify and save
      serviceVin.save(vine);

      // Create an "ok" response
      builder = Response.ok();
    } catch (ConstraintViolationException ce) {
      // Handle bean validation issues
      builder = createViolationResponse(ce.getConstraintViolations());
    } catch (ValidationException e) {
      // Handle the unique constrain violation
      Map<String, String> responseObj = new HashMap<String, String>();
      responseObj.put("email", "Email taken");
      builder = Response.status(Response.Status.CONFLICT).entity(responseObj);
    } catch (Exception e) {
      // Handle generic exceptions
      Map<String, String> responseObj = new HashMap<String, String>();
      responseObj.put("error", e.getMessage());
      builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj);
    }

    return builder.build();
  }
  /**
   * Create Push Application
   *
   * @param pushApp new {@link PushApplication}
   * @return created {@link PushApplication}
   * @statuscode 201 The PushApplication Variant created successfully
   * @statuscode 400 The format of the client request was incorrect
   */
  @POST
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  @ReturnType("org.jboss.aerogear.unifiedpush.api.PushApplication")
  public Response registerPushApplication(PushApplication pushApp) {

    // some validation
    try {
      validateModelClass(pushApp);
    } catch (ConstraintViolationException cve) {

      // Build and return the 400 (Bad Request) response
      ResponseBuilder builder = createBadRequestResponse(cve.getConstraintViolations());

      return builder.build();
    }

    pushAppService.addPushApplication(pushApp);

    return Response.created(
            UriBuilder.fromResource(PushApplicationEndpoint.class)
                .path(String.valueOf(pushApp.getPushApplicationID()))
                .build())
        .entity(pushApp)
        .build();
  }
Ejemplo n.º 4
0
  private static void doSomething(ApplicationContext context) {
    OrderService orderService = context.getBean(OrderService.class);
    String customerId = "CUS0001";
    Item item = context.getBean(Item.class);
    item.setName("ITEM0001");
    item.setZipCode("110000");

    Order order = null;
    try {
      order = orderService.placeOrder(customerId, item, 3);
    } catch (ConstraintViolationException e) {
      // TODO Auto-generated catch block
      Set<ConstraintViolation<?>> results = e.getConstraintViolations();
      for (ConstraintViolation<?> result : results) {
        //			    System.out.println("校验错误信息模板: " + result.getMessageTemplate());
        System.out.println(
            ""
                + result.getLeafBean().getClass().getName()
                + "."
                + result.getPropertyPath()
                + ": "
                + result.getMessage());
        //				System.out.println(result.getConstraintDescriptor());
      }

      //			System.out.println(results);
    }
    System.out.println("返回的订单信息: " + order);
  }
  /**
   * Update Push Application
   *
   * @param pushApplicationID id of {@link PushApplication}
   * @param updatedPushApp new info of {@link PushApplication}
   * @statuscode 204 The PushApplication updated successfully
   * @statuscode 400 The format of the client request was incorrect
   * @statuscode 404 The requested PushApplication resource does not exist
   */
  @PUT
  @Path("/{pushAppID}")
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  @ReturnType("java.lang.Void")
  public Response updatePushApplication(
      @PathParam("pushAppID") String pushApplicationID, PushApplication updatedPushApp) {

    PushApplication pushApp = getSearch().findByPushApplicationIDForDeveloper(pushApplicationID);

    if (pushApp != null) {

      // some validation
      try {
        validateModelClass(updatedPushApp);
      } catch (ConstraintViolationException cve) {

        // Build and return the 400 (Bad Request) response
        ResponseBuilder builder = createBadRequestResponse(cve.getConstraintViolations());

        return builder.build();
      }

      // update name/desc:
      pushApp.setDescription(updatedPushApp.getDescription());
      pushApp.setName(updatedPushApp.getName());
      pushAppService.updatePushApplication(pushApp);

      return Response.noContent().build();
    }

    return Response.status(Status.NOT_FOUND)
        .entity("Could not find requested PushApplicationEntity")
        .build();
  }
  public void testBeanValidation() throws Exception {
    Artist a = new Artist();
    a.setName("TOO OLD ARTIST");
    a.setAge(120);

    XPersistence.getManager().persist(a);
    try {
      XPersistence.commit();
    } catch (RollbackException ex) {

      if (ex.getCause() instanceof javax.validation.ConstraintViolationException) {
        javax.validation.ConstraintViolationException vex =
            (javax.validation.ConstraintViolationException) ex.getCause();
        assertEquals("1 invalid value is expected", 1, vex.getConstraintViolations().size());
        ConstraintViolation violation = vex.getConstraintViolations().iterator().next();
        assertEquals("Bean", "Artist", violation.getRootBeanClass().getSimpleName());
        String expectedMessage =
            "es".equals(Locale.getDefault().getLanguage())
                ? "tiene que ser menor o igual que 90"
                : "must be less than or equal to 90";
        assertEquals("Message text", expectedMessage, violation.getMessage());
        return;
      }
    }
    fail("A constraint violation exception should be thrown");
  }
  public JsonObject execute(JsonObject request, Session session) {
    JsonObject response = null;
    try {
      logger.debug("[execute] ");
      ThreadLocalVariablesKeeper.setRequest(request);
      ThreadLocalVariablesKeeper.setSession(session);
      response = tryExecute(request, session);
      logger.debug("[execute] building final response");
    } catch (HiveException ex) {
      response = JsonMessageBuilder.createError(ex).build();
    } catch (ConstraintViolationException ex) {
      response =
          JsonMessageBuilder.createErrorResponseBuilder(
                  HttpServletResponse.SC_BAD_REQUEST, ex.getMessage())
              .build();
    } catch (org.hibernate.exception.ConstraintViolationException ex) {
      response =
          JsonMessageBuilder.createErrorResponseBuilder(
                  HttpServletResponse.SC_CONFLICT, ex.getMessage())
              .build();
    } catch (JsonParseException ex) {
      response =
          JsonMessageBuilder.createErrorResponseBuilder(
                  HttpServletResponse.SC_BAD_REQUEST, Messages.INVALID_REQUEST_PARAMETERS)
              .build();
    } catch (OptimisticLockException ex) {
      response =
          JsonMessageBuilder.createErrorResponseBuilder(
                  HttpServletResponse.SC_CONFLICT, Messages.CONFLICT_MESSAGE)
              .build();
    } catch (PersistenceException ex) {
      if (ex.getCause() instanceof org.hibernate.exception.ConstraintViolationException) {
        response =
            JsonMessageBuilder.createErrorResponseBuilder(
                    HttpServletResponse.SC_CONFLICT, ex.getMessage())
                .build();
      } else {
        response =
            JsonMessageBuilder.createErrorResponseBuilder(
                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage())
                .build();
      }
    } catch (Exception ex) {
      response =
          JsonMessageBuilder.createErrorResponseBuilder(
                  HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage())
              .build();
    } finally {
      ThreadLocalVariablesKeeper.setRequest(null);
      ThreadLocalVariablesKeeper.setSession(null);
    }

    logger.debug("[execute] building final response");
    return new JsonMessageBuilder()
        .addAction(request.get(JsonMessageBuilder.ACTION).getAsString())
        .addRequestId(request.get(JsonMessageBuilder.REQUEST_ID))
        .include(response)
        .build();
  }
Ejemplo n.º 8
0
 /**
  * @param e
  * @param errorCode
  * @param propertyPath
  */
 public static void assertViolationContainsTemplateAndPath(
     final ConstraintViolationException e, final String errorCode, final String propertyPath) {
   Assert.assertNotNull(e.getConstraintViolations());
   Assert.assertEquals(1, CollectionUtils.size(e.getConstraintViolations()));
   final ConstraintViolation<?> violation = e.getConstraintViolations().iterator().next();
   Assert.assertEquals(errorCode, violation.getMessageTemplate());
   Assert.assertEquals(propertyPath, violation.getPropertyPath().toString());
 }
Ejemplo n.º 9
0
 @Test
 public void readInvalidClusterWithMissingZoneId() {
   try {
     readCluster("cluster-invalid-2.yml");
     Assert.fail("Expected violation");
   } catch (ConstraintViolationException e) {
     Assert.assertEquals(
         "id of zone is mandatory", e.getConstraintViolations().iterator().next().getMessage());
   }
 }
  @Test
  public void nameIsNull() {
    Address a = new Address(null, 34, 28);

    try {
      addressRepo.save(a);
    } catch (ConstraintViolationException cve) {
      assertEquals(1, cve.getConstraintViolations().size());
    }
  }
Ejemplo n.º 11
0
 @Test
 public void readInvalidClusterWithInvalidPartition() {
   try {
     readCluster("cluster-invalid-3.yml");
     Assert.fail("Expected violation");
   } catch (ConstraintViolationException e) {
     Assert.assertEquals(
         "partition id must not be greater than 65535",
         e.getConstraintViolations().iterator().next().getMessage());
   }
 }
Ejemplo n.º 12
0
 @Test
 public void readInvalidClusterWithEmptyName() {
   try {
     readCluster("cluster-invalid-1.yml");
     Assert.fail("Expected violation");
   } catch (ConstraintViolationException e) {
     Assert.assertEquals(
         "name of cluster is mandatory",
         e.getConstraintViolations().iterator().next().getMessage());
   }
 }
Ejemplo n.º 13
0
  @Test
  public void testValidation() throws Exception {

    final String value = Strings.random(16);

    ValidatedBean bean = new ValidatedBean();

    assertNull(bean.getValue());

    /* Null test! */
    try {
      store.store(bean);
      fail("ConstraintViolationException not thrown");
    } catch (ConstraintViolationException exception) {
      final Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();
      assertEquals(violations.size(), 1, "Wrong number of violations");
      final ConstraintViolation<?> violation = violations.iterator().next();
      assertNotNull(violation, "Null violation");
      assertEquals(
          violation.getMessage(), "The null value shall not be saved!", "Wrong violation message");
      assertEquals(violation.getPropertyPath().toString(), "value", "Wrong violation path");

      System.out.println(violation.getPropertyPath().toString());
      // TODO validate!
    }

    /* Empty string test! */
    try {
      bean.setValue("");
      store.store(bean);
      fail("ConstraintViolationException not thrown");
    } catch (ConstraintViolationException exception) {
      final Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();
      assertEquals(violations.size(), 1, "Wrong number of violations");
      final ConstraintViolation<?> violation = violations.iterator().next();
      assertNotNull(violation, "Null violation");
      assertEquals(
          violation.getMessage(),
          "The value shall be longer than 1 characters!",
          "Wrong violation message");
      assertEquals(violation.getPropertyPath().toString(), "value", "Wrong violation path");
    }

    /* Good value test! */
    bean.setValue(value);
    bean = store.store(bean);
    assertNotNull(bean, "Null stored bean");
    assertEquals(bean.value, value, "Wrong stored value");

    /* Re-read to ensure */
    bean = store.find(bean.id());
    assertNotNull(bean, "Null retrieved bean");
    assertEquals(bean.value, value, "Wrong retrieved value");
  }
 @Test
 public void testApplication() throws IOException, Exception {
   try {
     LocalMode lma = LocalMode.newInstance();
     Configuration conf = new Configuration(false);
     conf.addResource(this.getClass().getResourceAsStream("/META-INF/properties.xml"));
     lma.prepareDAG(new Application(), conf);
     LocalMode.Controller lc = lma.getController();
     lc.run(10000); // runs for 10 seconds and quits
   } catch (ConstraintViolationException e) {
     Assert.fail("constraint violations: " + e.getConstraintViolations());
   }
 }
  @Test
  public void nameIsTooShort() {
    Address a = new Address("abc", 45, 37);

    try {
      addressRepo.save(a);
    } catch (ConstraintViolationException cve) {
      assertEquals(1, cve.getConstraintViolations().size());
      assertEquals(
          "The Field Name must contains almost 4 characters.",
          cve.getConstraintViolations().iterator().next().getMessage());
    }
  }
 @Override
 public void createBluetoothDwell(BluetoothDwell entry) {
   try {
     em.persist(entry);
   } catch (javax.validation.ConstraintViolationException err) {
     logger.error(err.getConstraintViolations().toString());
   } catch (javax.ejb.EJBException err) {
     Throwable cause = err.getCause();
     if (cause instanceof ConstraintViolationException) {
       logger.error(((ConstraintViolationException) cause).getConstraintViolations().toString());
     }
   } catch (Exception err) {
     logger.error(null, err);
   }
 }
Ejemplo n.º 17
0
  @Test(expected = ConstraintViolationException.class)
  public void validateKoodisto() {
    try {
      insertValidKoodisto();
    } catch (Exception e) {
      fail();
    }

    try {
      genericDAO.insert(new Koodisto());
    } catch (ConstraintViolationException e) {
      assertEquals(2, e.getConstraintViolations().size());
      throw e;
    }
  }
Ejemplo n.º 18
0
  @Test(expected = ConstraintViolationException.class)
  public void validateInvalidKoodistoVersioValidityDates() {
    Koodisto koodisto = insertValidKoodisto();
    Calendar now = Calendar.getInstance();

    KoodistoVersio invalidKoodistoVersio =
        createKoodistoVersioWithValidityDates(
            koodisto, now.getTime(), new Date(now.getTimeInMillis() - 1L));
    try {
      genericDAO.insert(invalidKoodistoVersio);
    } catch (ConstraintViolationException e) {
      assertEquals(2, e.getConstraintViolations().size());
      throw e;
    }
  }
 public ConstraintViolationExceptionMessage(
     ConstraintViolationException cve, MessageSource msgSrc, Locale locale) {
   this.cve = cve;
   for (ConstraintViolation cv : cve.getConstraintViolations()) {
     messages.add(new ConstraintViolationMessage(cv, msgSrc, locale));
   }
 }
  // new Android
  @POST
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  public Response registerAndroidVariant(
      AndroidVariant androidVariant,
      @PathParam("pushAppID") String pushApplicationID,
      @Context UriInfo uriInfo,
      @Context HttpServletRequest request) {

    // find the root push app
    PushApplication pushApp =
        pushAppService.findByPushApplicationIDForDeveloper(
            pushApplicationID, request.getUserPrincipal().getName());

    if (pushApp == null) {
      return Response.status(Status.NOT_FOUND)
          .entity("Could not find requested PushApplicationEntity")
          .build();
    }

    // some validation
    try {
      validateModelClass(androidVariant);
    } catch (ConstraintViolationException cve) {

      // Build and return the 400 (Bad Request) response
      ResponseBuilder builder = createBadRequestResponse(cve.getConstraintViolations());

      return builder.build();
    }

    // store the "developer:
    androidVariant.setDeveloper(request.getUserPrincipal().getName());

    // store the Android variant:
    variantService.addVariant(androidVariant);
    // add iOS variant, and merge:
    pushAppService.addAndroidVariant(pushApp, androidVariant);

    return Response.created(
            uriInfo
                .getAbsolutePathBuilder()
                .path(String.valueOf(androidVariant.getVariantID()))
                .build())
        .entity(androidVariant)
        .build();
  }
 @Test
 public void testListeners() {
   CupHolder ch = new CupHolder();
   ch.setRadius(new BigDecimal("12"));
   Session s = openSession();
   Transaction tx = s.beginTransaction();
   try {
     s.persist(ch);
     s.flush();
     fail("invalid object should not be persisted");
   } catch (ConstraintViolationException e) {
     assertEquals(1, e.getConstraintViolations().size());
     assertEquals("Oops", e.getConstraintViolations().iterator().next().getMessage());
   }
   tx.rollback();
   s.close();
 }
 @Override
 public void updateBluetoothFileSendSummary(BluetoothFileSendSummary entry) {
   try {
     em.merge(entry);
   } catch (javax.validation.ConstraintViolationException err) {
     logger.error(err.getConstraintViolations().toString());
   } catch (javax.ejb.EJBException err) {
     Throwable cause = err.getCause();
     if (cause instanceof ConstraintViolationException) {
       logger.error(((ConstraintViolationException) cause).getConstraintViolations().toString());
     } else {
       logger.error(null, err);
     }
   } catch (Exception err) {
     logger.error(null, err);
   }
 }
Ejemplo n.º 23
0
  public void testInsertWithEmbedded() {
    try {
      EntityManager em = getEM();
      EntityTransaction tx = em.getTransaction();
      try {
        tx.begin();
        ValidatedOwner owner = new ValidatedOwner(1, "First Owner");
        ValidatedPet pet = new ValidatedPet(null);
        owner.setPet(pet);
        em.persist(owner);
        tx.commit();
        fail("Should have thrown exception with null embedded field, but persisted!");
      } catch (ConstraintViolationException cve) {
        // Expected
        LOG.info(
            "Threw exception when attempting persist of object with null NotNull embedded field");
      } finally {
        if (tx.isActive()) {
          tx.rollback();
        }
        em.close();
      }

      em = getEM();
      tx = em.getTransaction();
      try {
        tx.begin();
        ValidatedOwner owner = new ValidatedOwner(1, "First Owner");
        ValidatedPet pet = new ValidatedPet("Fluffy");
        owner.setPet(pet);
        em.persist(owner);
        tx.commit();
      } catch (ConstraintViolationException cve) {
        LOG.error("Exception in persist of object with transient not null field", cve);
        fail("Should have persisted ok but exception thrown : " + cve.getMessage());
      } finally {
        if (tx.isActive()) {
          tx.rollback();
        }
        em.close();
      }
    } finally {
      clean(ValidatedOwner.class);
    }
  }
 private void checkConstraint(String expected, ConstraintViolationException e) {
   for (ConstraintViolation<?> constraintViolation : e.getConstraintViolations()) {
     String actual = constraintViolation.getPropertyPath().toString();
     if (actual.equals(expected)) {
       return;
     }
   }
   fail();
 }
Ejemplo n.º 25
0
  @Test(expected = ConstraintViolationException.class)
  public void validateKoodiMetadata() {
    KoodiVersio koodiVersio = insertValidKoodiVersio(insertValidKoodi(insertValidKoodisto()));

    try {
      KoodiMetadata koodiMetadata = createValidKoodiMetadata(Kieli.SV);
      koodiMetadata.setKoodiVersio(koodiVersio);
      genericDAO.insert(koodiMetadata);
    } catch (Exception e) {
      fail();
    }

    try {
      genericDAO.insert(new KoodiMetadata());
    } catch (ConstraintViolationException e) {
      assertEquals(3, e.getConstraintViolations().size());
      throw e;
    }
  }
 /** 处理JSR311 Validation异常. */
 @ExceptionHandler(value = {ConstraintViolationException.class})
 public final ResponseEntity<?> handleException(
     ConstraintViolationException ex, WebRequest request) {
   Map<String, String> errors =
       BeanValidators.extractPropertyAndMessage(ex.getConstraintViolations());
   String body = jsonMapper.toJson(errors);
   HttpHeaders headers = new HttpHeaders();
   headers.setContentType(MediaType.parseMediaType(MediaTypes.TEXT_PLAIN_UTF_8));
   return handleExceptionInternal(ex, body, headers, HttpStatus.BAD_REQUEST, request);
 }
Ejemplo n.º 27
0
  public void testInsertTransientNotNull() {
    try {
      EntityManager em = getEM();
      EntityTransaction tx = em.getTransaction();
      try {
        tx.begin();
        ValidatedPerson2 p1 = new ValidatedPerson2(1, "Fred", "Bloggs");
        em.persist(p1);
        tx.commit();
        fail("Should have thrown exception with null transient field, but persisted!");
      } catch (ConstraintViolationException cve) {
        // Expected
        LOG.info(
            "Threw exception when attempting persist of object with null NotNull transient field");
      } finally {
        if (tx.isActive()) {
          tx.rollback();
        }
        em.close();
      }

      em = getEM();
      tx = em.getTransaction();
      try {
        tx.begin();
        ValidatedPerson2 p1 = new ValidatedPerson2(1, "Fred", "Bloggs");
        p1.setPassword("topsecret");
        em.persist(p1);
        tx.commit();
      } catch (ConstraintViolationException cve) {
        LOG.error("Exception in persist of object with transient not null field", cve);
        fail("Should have persisted ok but exception thrown : " + cve.getMessage());
      } finally {
        if (tx.isActive()) {
          tx.rollback();
        }
        em.close();
      }
    } finally {
      clean(ValidatedPerson2.class);
    }
  }
  public void testRequiredAsBeanValidationAnnotation() throws Exception {
    DrivingLicence dl = new DrivingLicence();
    dl.setType("X");
    dl.setLevel(1);
    dl.setDescription(""); // This is annotated with @Required

    XPersistence.getManager().persist(dl);
    try {
      XPersistence.commit();
    } catch (RollbackException ex) {
      if (ex.getCause() instanceof ConstraintViolationException) {
        ConstraintViolationException cex = (ConstraintViolationException) ex.getCause();
        assertEquals("1 constraint violation expected", 1, cex.getConstraintViolations().size());
        ConstraintViolation v = cex.getConstraintViolations().iterator().next();
        assertEquals("Property", "description", v.getPropertyPath().toString());
        assertEquals("Message text", "{required}", v.getMessage());
        return;
      }
    }
    fail("A constraint violation exception should be thrown");
  }
  @AroundInvoke
  public Object execute(final InvocationContext ictx) throws Exception {
    try {
      return ictx.proceed();
    } catch (ConstraintViolationException e) {
      final Logger log = getLogger(ictx.getTarget().getClass());
      log.error("***********************************************************");
      log.error(
          ictx.getMethod().toGenericString()
              + asList(ictx.getParameters())
              + " had the following validation errors: ");

      Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
      for (ConstraintViolation<?> violation : violations) {
        log.error(buildViolationMessage(violation));
      }

      log.error("***********************************************************");

      throw e;
    }
  }
Ejemplo n.º 30
0
  public void init() {
    int from = 0;
    int to = 10;
    data =
        cartRepository
            .findAll(new org.springframework.data.domain.PageRequest(from / to, to))
            .getContent();
    if (data == null) {
      throw new IllegalStateException(
          "Find entries implementation for 'Cart' illegally returned null");
    }
    if (!data.isEmpty()) {
      return;
    }

    data = new ArrayList<Cart>();
    for (int i = 0; i < 10; i++) {
      Cart obj = getNewTransientCart(i);
      try {
        cartRepository.save(obj);
      } catch (ConstraintViolationException e) {
        StringBuilder msg = new StringBuilder();
        for (Iterator<ConstraintViolation<?>> iter = e.getConstraintViolations().iterator();
            iter.hasNext(); ) {
          ConstraintViolation<?> cv = iter.next();
          msg.append("[")
              .append(cv.getConstraintDescriptor())
              .append(":")
              .append(cv.getMessage())
              .append("=")
              .append(cv.getInvalidValue())
              .append("]");
        }
        throw new RuntimeException(msg.toString(), e);
      }
      cartRepository.flush();
      data.add(obj);
    }
  }