/*
 * 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.lifecycle;

import javax.jdo.Transaction;
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.pc.lifecycle.StateTransitionObj;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Test Transient Transactional Rollback <br>
 * <B>Keywords:</B> lifecycle transienttransactional rollback <br>
 * <B>Assertion IDs:</B> A5.1-4 <B>Assertion Description: </B> If <code>TransientTransactional
 * </code> is supported, a transient transactional instance will have its state restored to its
 * state prior to becoming transactional when its associated transaction aborts or on rollback.
 */
public class TransientTransactionalStateRollback extends JDO_Test {

  /** */
  private static final String ASSERTION_FAILED =
      "Assertion A5.1-4 (TransientTransactionalStateRollback) failed: ";

  private static final int CLEAN_VALUE = 12;
  private static final int DIRTY_VALUE = 123;

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

  /** */
  public void test() {
    if (!isTransientTransactionalSupported()) {
      logger.debug("Transient transactional instances are not supported");
    } else {
      pm = getPM();

      // Get transient instance and read field value
      StateTransitionObj obj = getTransientInstance();

      int beforeValue = obj.readField();

      // Start transaction
      Transaction tx = pm.currentTransaction();
      tx.begin();

      // Get transient dirty instance
      makeTransientDirty(obj);

      // Rollback
      tx.rollback();
      int curr = currentState(obj);
      if (curr != TRANSIENT_CLEAN) {
        fail(
            ASSERTION_FAILED,
            "StateTransition: Unable to create transient-clean instance "
                + "from a transient-dirty instance via tx.rollback(), state is "
                + states[curr]);
      }

      // Check that field value has been rolled back
      int afterValue = obj.readField();
      if (beforeValue != afterValue) {
        fail(
            ASSERTION_FAILED,
            "Field value incorrect after rollback. Expected: "
                + beforeValue
                + " Found: "
                + afterValue);
      }
    }
  }

  protected StateTransitionObj getTransientInstance() {
    StateTransitionObj obj = new StateTransitionObj(CLEAN_VALUE);
    int curr = currentState(obj);
    if (curr != TRANSIENT) {
      fail(ASSERTION_FAILED, "Unable to create transient instance, state is " + states[curr]);
    }
    return obj;
  }

  protected void makeTransientClean(StateTransitionObj obj) {
    if (obj == null) return;
    pm.makeTransactional(obj);
    int curr = currentState(obj);
    if (curr != TRANSIENT_CLEAN) {
      fail(
          ASSERTION_FAILED,
          "Unable to create transient-clean instance "
              + "from a transient instance via makeTransactional(), state is "
              + states[curr]);
    }
  }

  protected void makeTransientDirty(StateTransitionObj obj) {
    if (obj == null) return;
    makeTransientClean(obj);
    obj.writeField(DIRTY_VALUE);
    int curr = currentState(obj);
    if (curr != TRANSIENT_DIRTY) {
      fail(
          ASSERTION_FAILED,
          "Unable to create transient-dirty instance "
              + "from a transient-clean instance via modifying a field, state is "
              + states[curr]);
    }
  }
}
