/*
 * 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
<<<<<<< Updated upstream
 *
 *     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
=======
 * 
 *     https://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 
>>>>>>> Stashed changes
 * 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()));
      }
    }
  }
}
