/*
 * 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.jdo.tck.query.delete;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import javax.jdo.listener.DeleteLifecycleListener;
import javax.jdo.listener.InstanceLifecycleEvent;
import javax.jdo.listener.StoreLifecycleListener;
import org.apache.jdo.tck.pc.company.CompanyModelReader;
import org.apache.jdo.tck.pc.company.Department;
import org.apache.jdo.tck.pc.company.Employee;
import org.apache.jdo.tck.pc.company.IEmployee;
import org.apache.jdo.tck.pc.company.IProject;
import org.apache.jdo.tck.pc.company.Person;
import org.apache.jdo.tck.pc.company.Project;
import org.apache.jdo.tck.pc.mylib.MylibReader;
import org.apache.jdo.tck.pc.mylib.PrimitiveTypes;
import org.apache.jdo.tck.query.QueryElementHolder;
import org.apache.jdo.tck.query.QueryTest;
import org.apache.jdo.tck.util.BatchTestRunner;
import org.apache.jdo.tck.util.ConversionHelper;

/**
 * <B>Title:</B> Delete Persistent All. <br>
 * <B>Keywords:</B> query <br>
 * <B>Assertion ID:</B> A14.8-4 <br>
 * <B>Assertion Description: </B> Dirty instances of affected classes are first flushed to the
 * datastore. Instances already in the cache when deleted via these methods or brought into the
 * cache as a result of these methods undergo the life cycle transitions as if deletePersistent had
 * been called on them. That is, if an affected class implements the DeleteCallback interface, the
 * instances to be deleted are instantiated in memory and the jdoPreDelete method is called prior to
 * deleting the instance in the datastore. If any LifecycleListener instances are registered with
 * affected classes, these listeners are called for each deleted instance. Before returning control
 * to the application, instances of affected classes in the cache are refreshed by the
 * implementation so their status in the cache reflects whether they were deleted from the
 * datastore.
 */
public class DeleteCallback extends QueryTest {

  /** */
  private static final String ASSERTION_FAILED = "Assertion A14.8-4 (DeleteCallback) failed: ";

  /**
   * The array of valid queries which may be executed as single string queries and as API queries.
   */
  private static final QueryElementHolder<?>[] VALID_QUERIES = {
    new QueryElementHolder<>(
        /*UNIQUE*/ null,
        /*RESULT*/ null,
        /*INTO*/ null,
        /*FROM*/ Person.class,
        /*EXCLUDE*/ null,
        /*WHERE*/ null,
        /*VARIABLES*/ null,
        /*PARAMETERS*/ null,
        /*IMPORTS*/ null,
        /*GROUP BY*/ null,
        /*ORDER BY*/ null,
        /*FROM*/ null,
        /*TO*/ null),
    new QueryElementHolder<>(
        /*UNIQUE*/ null,
        /*RESULT*/ null,
        /*INTO*/ null,
        /*FROM*/ PrimitiveTypes.class,
        /*EXCLUDE*/ null,
        /*WHERE*/ null,
        /*VARIABLES*/ null,
        /*PARAMETERS*/ null,
        /*IMPORTS*/ null,
        /*GROUP BY*/ null,
        /*ORDER BY*/ null,
        /*FROM*/ null,
        /*TO*/ null)
  };

  /** The expected results of valid queries. */
  private final List<?>[] expectedResult = {
    getTransientCompanyModelInstancesAsList(Employee.class, "emp1", "emp2", "emp3", "emp4", "emp5"),
    getTransientMylibInstancesAsList(
        "primitiveTypesPositive", "primitiveTypesNegative", "primitiveTypesCharacterStringLiterals")
  };

  /**
   * The <code>main</code> is called when the class is directly executed from the command line.
   *
   * @param args The arguments passed to the program.
   */
  public static void main(String[] args) {
    BatchTestRunner.run(DeleteCallback.class);
  }

  /** */
  public void testRelationshipsAPI() {
    queryUpdateDeleteVerify(0, false, "middlename");
  }

  /** */
  public void testRelationshipsSingleString() {
    queryUpdateDeleteVerify(0, true, "middlename");
  }

  /** */
  public void testNoRelationshipsAPI() {
    queryUpdateDeleteVerify(1, false, "stringNull");
  }

  /** */
  public void testNoRelationshipsSingleString() {
    queryUpdateDeleteVerify(1, true, "stringNull");
  }

  /**
   * @see org.apache.jdo.tck.JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    addTearDownClass(CompanyModelReader.getTearDownClasses());
    addTearDownClass(MylibReader.getTearDownClasses());
    loadAndPersistCompanyModel(getPM());
    loadAndPersistMylib(getPM());
  }

  /**
   * Adds a lifecycle listener to the persistence manager.
   * Converts the query element holder instance refered to by argument
   * <code>index</code> to a JDO query instance based on argument
   * <code>asSingleString</code>.
   * Executes the query instance and marks all queried pc instances as dirty
   * by calling {@link JDOHelper#makeDirty(java.lang.Object, java.lang.String)}.
   * Passes argument <code>fieldName</code> to that call.
   * Afterwards, calls {@link Query#deletePersistentAll()}, and
   * verifies the lifecycle callbacks and the lifecycle states.
   * @param index the index of the query element holder instance
   * @param fieldName the field name passed as argument to
   * {@link JDOHelper#makeDirty(java.lang.Object, java.lang.String)
   * @param asSingleString determines if the query is executed as
   * single string query or as API query.
   */
  private void queryUpdateDeleteVerify(int index, boolean asSingleString, String fieldName) {
    PersistenceManager pm = getPM();
    Transaction transaction = pm.currentTransaction();
    transaction.begin();
    try {
      LifecycleVerifier lifecycleVerifier;
      Query<?> query =
          asSingleString
              ? VALID_QUERIES[index].getSingleStringQuery(pm)
              : VALID_QUERIES[index].getAPIQuery(pm);

      Collection<?> result = executeQuery(query, index, asSingleString);
      try {
        lifecycleVerifier = new LifecycleVerifier(result);
        pm.addInstanceLifecycleListener(
            lifecycleVerifier, VALID_QUERIES[index].getCandidateClass());
        updateInstances(result, fieldName);
        deleteInstances(query, index, asSingleString, result.size());
      } finally {
        query.close(result);
      }

      lifecycleVerifier.verifyCallbacksAndStates();
    } finally {
      if (transaction.isActive()) {
        transaction.rollback();
      }
    }
  }

  /**
   * Executes the given query, checks and returns the query result. Note: This mthod does not close
   * the query result.
   *
   * @param query the query.
   * @param index the index of the query element holder instance which was used to created the given
   *     query.
   * @param asSingleString indicates if the given query was created using API methods or if it was
   *     created by a single string.
   * @return the query result.
   */
  private Collection<?> executeQuery(Query<?> query, int index, boolean asSingleString) {
    if (logger.isDebugEnabled()) {
      if (asSingleString) {
        logger.debug("Executing single string query: " + VALID_QUERIES[index]);
      } else {
        logger.debug("Executing API query: " + VALID_QUERIES[index]);
      }
    }

    Collection<?> result = (Collection<?>) query.execute();

    if (logger.isDebugEnabled()) {
      logger.debug("Query result: " + ConversionHelper.convertObjectArrayElements(result));
    }

    checkQueryResultWithoutOrder(ASSERTION_FAILED, result, expectedResult[index]);
    return result;
  }

  /**
   * Makes all instances in the given collection dirty.
   * If instances are employees, then all relationships are cleared.
   * @param instances the instances
   * @param fieldName the field name passed as argument to
   * {@link JDOHelper#makeDirty(java.lang.Object, java.lang.String)
   */
  private void updateInstances(Collection<?> instances, String fieldName) {
    for (Object pc : instances) {
      // clear employee relationships
      if (pc instanceof Employee) {
        Employee employee = (Employee) pc;
        if (employee.getDentalInsurance() != null) {
          employee.getDentalInsurance().setEmployee(null);
        }
        if (employee.getMedicalInsurance() != null) {
          employee.getMedicalInsurance().setEmployee(null);
        }
        if (employee.getDepartment() != null) {
          ((Department) employee.getDepartment()).removeEmployee(employee);
        }
        if (employee.getFundingDept() != null) {
          ((Department) employee.getFundingDept()).removeEmployee(employee);
        }
        if (employee.getManager() != null) {
          ((Employee) employee.getManager()).removeFromTeam(employee);
        }
        if (employee.getMentor() != null) {
          employee.getMentor().setProtege(null);
        }
        if (employee.getProtege() != null) {
          employee.getProtege().setMentor(null);
        }
        if (employee.getHradvisor() != null) {
          ((Employee) employee.getHradvisor()).removeAdvisee(employee);
        }
        if (employee.getReviewedProjects() != null) {
          for (IProject iProject : employee.getReviewedProjects()) {
            Project other = (Project) iProject;
            other.removeReviewer(employee);
          }
        }
        if (employee.getProjects() != null) {
          for (IProject iProject : employee.getProjects()) {
            Project other = (Project) iProject;
            other.removeMember(employee);
          }
        }
        if (employee.getTeam() != null) {
          for (IEmployee iEmployee : employee.getTeam()) {
            Employee other = (Employee) iEmployee;
            other.setManager(null);
          }
        }
        if (employee.getHradvisees() != null) {
          for (IEmployee iEmployee : employee.getHradvisees()) {
            Employee other = (Employee) iEmployee;
            other.setHradvisor(employee);
          }
        }
      }

      // make the instance dirty.
      if (logger.isDebugEnabled()) {
        logger.debug("Calling JDOHelper.makeDirty(" + pc + ", \"" + fieldName + "\")");
      }
      JDOHelper.makeDirty(pc, fieldName);
    }
  }

  /**
   * Calls {@link Query#deletePersistentAll()} on the given query.
   *
   * @param query the query.
   * @param index the index of the query element holder instance which was used to created the given
   *     query.
   * @param asSingleString indicates if the given query was created using API methods or if it was
   *     created by a single string.
   * @param expectedNumberOfDeletedInstances the expected number of deleted instances.
   */
  private void deleteInstances(
      Query<?> query, int index, boolean asSingleString, int expectedNumberOfDeletedInstances) {
    if (logger.isDebugEnabled()) {
      if (asSingleString) {
        logger.debug("Deleting persistent by single string query: " + VALID_QUERIES[index]);
      } else {
        logger.debug("Deleting persistent by API query: " + VALID_QUERIES[index]);
      }
    }

    long nr = query.deletePersistentAll();

    if (logger.isDebugEnabled()) {
      logger.debug(nr + " objects deleted.");
    }

    if (nr != expectedNumberOfDeletedInstances) {
      fail(
          ASSERTION_FAILED,
          "deletePersistentAll returned "
              + nr
              + ", expected is "
              + expectedNumberOfDeletedInstances
              + ". Query: "
              + VALID_QUERIES[index]);
    }
  }

  /**
   * A lifecycle listener which may be added to persistence managers.
   * Gathers delete events and store events and keeps those
   * in a list.
   * Method {@link LifecycleVerifier#verifyCallbacksAndStates()}
   * may be called to check if the right events have been called
   * on all expected instances.
   * The expected instances are passed through
   * {@link LifecycleVerifier#LifecycleVerifier(Collection).
   */
  private class LifecycleVerifier implements DeleteLifecycleListener, StoreLifecycleListener {

    /** The oids of expected pc instances. */
    private final Collection<Object> expectedOids = new HashSet<>();

    /** The list of events. */
    private final List<InstanceLifecycleEvent> events = new ArrayList<>();

    /**
     * Argument <code>expectedPCInstances</code> holds pc instances which are expected to be sources
     * of events.
     *
     * @param expectedPCInstances the pc instances which are expected to be sources of events.
     */
    public LifecycleVerifier(Collection<?> expectedPCInstances) {
      for (Object expectedPCInstance : expectedPCInstances) {
        this.expectedOids.add(JDOHelper.getObjectId(expectedPCInstance));
      }
    }

    /**
     * Verifies if the right events have been called for all expected pc instances. All store events
     * must have been fired before the first delete event has been fired. Furthermore, checks if pc
     * instances kept in delete events have state persistent-deleted. The test case fails if one of
     * these conditions is violated.
     */
    public void verifyCallbacksAndStates() {
      if (logger.isDebugEnabled()) {
        logger.debug("Verifying callbacks and states.");
      }
      // The two collections are filled iterating through the list of
      // events. Finally, they are compared against field expectedOids.
      // Note: Set implementations are used instead of list
      // implementations to eliminate duplicates. Duplicates may occur
      // if multiple updates or deletions are executed for the same
      // pc instances.
      Collection<Object> oidsOfDeletedInstances = new HashSet<>();
      Collection<Object> oidsOfUpdateInstances = new HashSet<>();

      boolean hasDeleteEventBeenPassed = false;
      int size = events.size();
      for (InstanceLifecycleEvent event : events) {
        Object source = event.getSource();
        int eventType = event.getEventType();
        if (eventType == InstanceLifecycleEvent.DELETE) {
          if (logger.isDebugEnabled()) {
            logger.debug("Verifying delete event on " + JDOHelper.getObjectId(source));
          }
          hasDeleteEventBeenPassed = true;
          if (!JDOHelper.isDeleted(source)) {
            fail(
                ASSERTION_FAILED, "PC instance must have persistent deleted " + "state: " + source);
          }
          oidsOfDeletedInstances.add(JDOHelper.getObjectId(source));
        } else if (eventType == InstanceLifecycleEvent.STORE) {
          if (logger.isDebugEnabled()) {
            logger.debug("Verifying store event on " + JDOHelper.getObjectId(source));
          }

          if (hasDeleteEventBeenPassed) {
            fail(
                ASSERTION_FAILED,
                "PC instances must not be flushed " + "after delete has been executed.");
          }
          oidsOfUpdateInstances.add(JDOHelper.getObjectId(source));
        }
      }

      if (!equalsCollection(oidsOfDeletedInstances, this.expectedOids)) {
        String lf = System.getProperty("line.separator");
        fail(
            ASSERTION_FAILED,
            "Got delete events for oids "
                + oidsOfDeletedInstances
                + '.'
                + lf
                + "Expected deleted events for oids "
                + this.expectedOids
                + '.');
      } else if (!oidsOfUpdateInstances.containsAll(this.expectedOids)) {
        String lf = System.getProperty("line.separator");
        fail(
            ASSERTION_FAILED,
            "Got store events for oids "
                + oidsOfUpdateInstances
                + '.'
                + lf
                + "Expected store events for oids "
                + this.expectedOids
                + '.');
      }
    }

    /**
     * @see DeleteLifecycleListener#preDelete(javax.jdo.listener.InstanceLifecycleEvent)
     */
    public void preDelete(InstanceLifecycleEvent event) {
      if (logger.isDebugEnabled()) {
        logger.debug("preDelete event: " + JDOHelper.getObjectId(event.getSource()));
      }
    }

    /**
     * @see DeleteLifecycleListener#postDelete(javax.jdo.listener.InstanceLifecycleEvent)
     */
    public void postDelete(InstanceLifecycleEvent event) {
      this.events.add(event);
      if (logger.isDebugEnabled()) {
        logger.debug("postDelete event: " + JDOHelper.getObjectId(event.getSource()));
      }
    }

    /**
     * @see StoreLifecycleListener#preStore(javax.jdo.listener.InstanceLifecycleEvent)
     */
    public void preStore(InstanceLifecycleEvent event) {
      if (logger.isDebugEnabled()) {
        logger.debug("preStore event: " + JDOHelper.getObjectId(event.getSource()));
      }
    }

    /**
     * @see StoreLifecycleListener#postStore(javax.jdo.listener.InstanceLifecycleEvent)
     */
    public void postStore(InstanceLifecycleEvent event) {
      this.events.add(event);
      if (logger.isDebugEnabled()) {
        logger.debug("postStore event: " + JDOHelper.getObjectId(event.getSource()));
      }
    }
  }
}
