/*
 * 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.api.persistencemanager.cache;

import javax.jdo.Transaction;
import org.apache.jdo.tck.api.persistencemanager.PersistenceManagerTest;
import org.apache.jdo.tck.pc.mylib.PCPoint2;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Evicting With RetainValues False <br>
 * <B>Keywords:</B> cache <br>
 * <B>Assertion ID:</B> A12.5.1-3. <br>
 * <B>Assertion Description: </B> If users wish to automatically <code>evict</code> transactional
 * instances at transaction <code>commit</code> time, then they should set <code>RetainValues</code>
 * to <code>false</code>. For each persistent-clean instance that the JDO <code>PersistenceManager
 * </code> evicts, it:
 *
 * <UL>
 *   <LI>calls the <code>jdoPreClear</code> method on each instance, if the class of the instance
 *       implements <code>InstanceCallbacks</code>
 *   <LI>clears persistent fields on each instance (sets the value of the field to its Java default
 *       value)
 *   <LI>changes the state of instances to hollow
 * </UL>
 */
public class EvictingWithRetainValuesFalse extends PersistenceManagerTest {

  /** */
  private static final String ASSERTION_FAILED =
      "Assertion A12.5.1-3 (EvictingWithRetainValuesFalse) failed: ";

  /**
   * 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(EvictingWithRetainValuesFalse.class);
  }

  /**
   * @see org.apache.jdo.tck.JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    addTearDownClass(PCPoint2.class);
    super.localSetUp();
  }

  /** */
  public void test() {

    if (!isRetainValuesSupported()) {
      printUnsupportedOptionalFeatureNotTested(
          getClass().getName(), "javax.jdo.option.RetainValues");
    } else {
      pm = getPM();
      PCPoint2 pt = getHollowInstance();

      Transaction tx = pm.currentTransaction();
      tx.setRetainValues(
          false); // This should cause eviction of transactional instances when transaction is later
      // commited.

      // Test
      tx.begin();
      makePersistentClean(pt);
      tx.commit(); // This should evict pt
      verify(pt);
    }
  }

  /** */
  private PCPoint2 getHollowInstance() {
    Transaction tx = pm.currentTransaction();
    tx.begin();
    PCPoint2 pt = new PCPoint2(1, 2);
    pm.makePersistent(pt);
    tx.commit();

    int curr = currentState(pt);
    if (curr != HOLLOW) {
      fail(ASSERTION_FAILED, "Unable to create HOLLOW instance, state is " + states[curr]);
    }
    return pt;
  }

  /**
   * @param pt PCPoint2 instance
   */
  private void makePersistentClean(PCPoint2 pt) {
    pm.makeTransactional(pt);
    int curr = currentState(pt);
    if (curr != PERSISTENT_CLEAN) {
      fail(
          ASSERTION_FAILED, "Unable to create PERSISTENT_CLEAN instance, state is " + states[curr]);
    }
  }

  /**
   * @param pt PCPoint2 instance
   */
  private void verify(PCPoint2 pt) {
    // When PersistenceManager evicts instances, it: calls the jdoPreClear method on each instance
    if (!pt.wasClearCalled()) {
      fail(ASSERTION_FAILED, "missing call of jdoPreClear");
    }

    // When PersistenceManager evicts instances, it: changes the state of the instances to hollow
    int curr = currentState(pt);
    if ((curr != HOLLOW) && (curr != PERSISTENT_NONTRANSACTIONAL)) {
      fail(
          ASSERTION_FAILED,
          "Instance should be HOLLOW after tx.commit(), state is " + states[curr]);
    }

    pm.makeTransient(pt);
    // When PersistenceManager evicts instances, it: clears persistent fields on each instance (sets
    // the value of the field to its Java default value)
    int x = pt.getX();
    Integer y = pt.getY();
    if ((x != 0) || (y != null)) {
      fail(
          ASSERTION_FAILED,
          "persistent fields not cleared, pt.getX()==" + x + " and pt.getY()==" + y);
    }
  }
}
