content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.camel.quarkus.component.nitrite.it;
  
  import java.util.GregorianCalendar;
  
  import io.quarkus.test.common.QuarkusTestResource;
  import io.quarkus.test.junit.QuarkusTest;
  import io.restassured.RestAssured;
  import io.restassured.http.ContentType;
  import org.apache.camel.component.nitrite.NitriteConstants;
  import org.dizitart.no2.Document;
  import org.junit.jupiter.api.MethodOrderer;
  import org.junit.jupiter.api.Test;
  import org.junit.jupiter.api.TestMethodOrder;
  
  import static org.hamcrest.core.Is.is;
  
  @QuarkusTest
  @QuarkusTestResource(NitriteTestResource.class)
  @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
  class NitriteTest {
  
      private static final EmployeeSerializable sheldonSerializable = new EmployeeSerializable(1L,
              new GregorianCalendar(2010, 10, 1).getTime(),
              "Sheldon",
              "Alpha Centauri");
      private static final EmployeeSerializable leonardSerializable = new EmployeeSerializable(2L,
              new GregorianCalendar(2015, 10, 1).getTime(),
              "Leonard", "Earth");
      private static final EmployeeSerializable irmaSerializable = new EmployeeSerializable(3L,
              new GregorianCalendar(2011, 10, 1).getTime(),
              "Irma",
              "Jupiter");
  
      private static final EmployeeMappable sheldonMappable = new EmployeeMappable(1L,
              new GregorianCalendar(2010, 10, 1).getTime(),
              "Sheldon",
              "Alpha Centauri");
      private static final EmployeeMappable leonardMappable = new EmployeeMappable(2L,
              new GregorianCalendar(2015, 10, 1).getTime(),
              "Leonard", "Earth");
      private static final EmployeeMappable irmaMappable = new EmployeeMappable(3L, new GregorianCalendar(2011, 10, 1).getTime(),
              "Irma",
              "Jupiter");
  
      @Test
      public void repositoryClassSerializable() throws CloneNotSupportedException {
          testRepositoryClass(sheldonSerializable, leonardSerializable, irmaSerializable);
      }
  
      @Test
      public void repositoryClassMappable() throws CloneNotSupportedException {
          testRepositoryClass(sheldonMappable, leonardMappable, irmaMappable);
      }
  
      private void testRepositoryClass(Employee sheldon, Employee leonard, Employee irma)
              throws CloneNotSupportedException {
          boolean mappable = sheldon instanceof EmployeeMappable;
          /* Make sure there is no event there before we start inserting */
          RestAssured.get("/nitrite/getRepositoryClass?mappable=" + mappable)
                  .then()
                  .statusCode(204);
  
          /* Insert Sheldon */
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .queryParam("mappable", mappable)
                  .body(sheldon)
                  .post("/nitrite/repositoryClass")
                  .then()
                  .statusCode(200)
                  .body("name", is("Sheldon"));
          RestAssured.get("/nitrite/getRepositoryClass?mappable=" + mappable)
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "INSERT")
                  .body("name", is("Sheldon"));
  
          /* Insert Leonard */
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .queryParam("mappable", mappable)
                  .body(leonard)
                  .post("/nitrite/repositoryClass")
                  .then()
                  .statusCode(200)
                  .body("name", is("Leonard"));
          RestAssured.get("/nitrite/getRepositoryClass?mappable=" + mappable)
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "INSERT")
                  .body("name", is("Leonard"));
  
          /* Insert Irma */
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .queryParam("mappable", mappable)
                  .body(irma)
                  .post("/nitrite/repositoryClass")
                  .then()
                  .statusCode(200)
                  .body("name", is("Irma"));
          RestAssured.get("/nitrite/getRepositoryClass?mappable=" + mappable)
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "INSERT")
                  .body("name", is("Irma"));
  
          Employee updatedSheldon = null;
          if (sheldon instanceof EmployeeSerializable) {
              updatedSheldon = (EmployeeSerializable) sheldon.clone();
          } else {
              updatedSheldon = (EmployeeMappable) sheldon.clone();
          }
          updatedSheldon.setAddress("Moon");
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.update, "name", "Sheldon",
                          mappable ? null : (EmployeeSerializable) updatedSheldon,
                          mappable ? (EmployeeMappable) updatedSheldon : null))
                  .queryParam("mappable", mappable)
                  .post("/nitrite/repositoryClassOperation")
                  .then()
                  .body("name", is("Sheldon"),
                          "address", is("Moon"));
  
          RestAssured.get("/nitrite/getRepositoryClass?mappable=" + mappable)
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "UPDATE")
                  .body("name", is("Sheldon"),
                          "address", is("Moon"));
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.find, "address", (Object) "Moon", null, null))
                  .queryParam("mappable", mappable)
                  .post("/nitrite/repositoryClassOperation")
                  .then()
                  .statusCode(200)
                  .body("size()", is(1), // After the update, there is 1 employee from the Moon
                          "[0].name", is("Sheldon"));
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.findGt, "empId", (Object) 0, null, null))
                  .queryParam("mappable", mappable)
                  .post("/nitrite/repositoryClassOperation")
                  .then()
                  .statusCode(200)
                  .body("size()", is(3));// there are 3 employees in total
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.delete, "address", "Moon", null, null))
                  .queryParam("mappable", mappable)
                  .post("/nitrite/repositoryClassOperation")
                  .then()
                  .statusCode(204);
  
          RestAssured
                  .get("/nitrite/getRepositoryClass?mappable=" + mappable)
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "REMOVE")
                  .body("name", is("Sheldon"),
                          "address", is("Moon"));
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.findGt, "empId", (Object) 0, null, null))
                  .queryParam("mappable", mappable)
                  .post("/nitrite/repositoryClassOperation")
                  .then()
                  .statusCode(200)
                  .body("size()", is(2));// there are 2 employees after the deletion
  
      }
  
      @Test
      public void collection() throws Exception {
          /* Make sure there is no event there before we start inserting */
          RestAssured.get("/nitrite/collection")
                  .then()
                  .statusCode(204);
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(Document.createDocument("key1", "value1"))
                  .post("/nitrite/collection")
                  .then()
                  .statusCode(200)
                  .body("key1", is("value1"));
          RestAssured.get("/nitrite/collection")
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "INSERT")
                  .body("key1", is("value1"));
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(Document.createDocument("key2", "value2"))
                  .post("/nitrite/collection")
                  .then()
                  .statusCode(200)
                  .body("key2", is("value2"));
          RestAssured.get("/nitrite/collection")
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "INSERT")
                  .body("key2", is("value2"));
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.insert, null, null, Document.createDocument("key1", "value_beforeUpdate")))
                  .post("/nitrite/collectionOperation")
                  .then()
                  .statusCode(200)
                  .body("key1", is("value_beforeUpdate"));
          RestAssured.get("/nitrite/collection")
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "INSERT")
                  .body("key1", is("value_beforeUpdate"));
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.update, "key1", "value_beforeUpdate",
                          Document.createDocument("key1", "value_afterUpdate")))
                  .post("/nitrite/collectionOperation")
                  .then()
                  .statusCode(200)
                  .body("key1", is("value_afterUpdate"));
          RestAssured.get("/nitrite/collection")
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "UPDATE")
                  .body("key1", is("value_afterUpdate"));
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.delete, "key1", "value1", (Document) null))
                  .post("/nitrite/collectionOperation")
                  .then()
                  .statusCode(204);
          RestAssured.get("/nitrite/collection")
                  .then()
                  .statusCode(200)
                  .header(NitriteConstants.CHANGE_TYPE, "REMOVE")
                  .body("key1", is("value1"));
  
          RestAssured.given()
                  .contentType(ContentType.JSON)
                  .body(new Operation(Operation.Type.find, "key1", (Object) "value_afterUpdate", null))
                  .post("/nitrite/collectionOperation")
                  .then()
                  .statusCode(200)
                  .body("size()", is(1));// There is only 1 item with value1
      }
  
  }
  