/*
 * 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 java.util.Iterator;
import javax.jdo.Extent;
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 that a PM returns the same JDO instance if getObjectById(ObjectId) is called
 * multiple times with the same objectId instance <br>
 * <B>Keywords:</B> lifecycle getObjectById <br>
 * <B>Assertion IDs:</B> A5.4-2, A5.4-8 <br>
 * <B>Assertion Description: </B> Any instances returned by any calls to getObjectById(Object) with
 * the same object id instance to the same PersistenceManager instance must be identical (assuming
 * the instances were not garbage collected between calls).
 */
public class PMReturnsIdenticalInstancesForEqualObjIds extends JDO_Test {

  /** */
  private static final String ASSERTION_FAILED =
      "Assertions A5.4-2, A5.4-8 (PMReturnsIdenticalInstancesForEqualObjIds) failed: ";

  private static final int NUM_OBJECTS = 50;

  /** The persistent instances of this test. */
  private Object[] obj;

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

  /**
   * @see org.apache.jdo.tck.JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    pm = getPM();
    addTearDownClass(StateTransitionObj.class);
    obj = generatePersistentInstances();
  }

  public void test() {
    pm.currentTransaction().begin();
    try {
      Extent<StateTransitionObj> extent = pm.getExtent(StateTransitionObj.class, false);
      Iterator<StateTransitionObj> iter = extent.iterator();
      if (!iter.hasNext()) {
        fail(ASSERTION_FAILED, "Extent for StateTransitionObj should not be empty");
      }
      extent.close(iter);

      for (int i = 0; i < NUM_OBJECTS; i++) {
        Object objId = pm.getObjectId(obj[i]);
        // check that getObjectById returns identical instance
        Object obj2 = pm.getObjectById(objId, true);
        if (!(obj2 == obj[i])) {
          fail(ASSERTION_FAILED, "objects with OId = " + objId + " are not identical");
        }
      }
      pm.currentTransaction().commit();
    } finally {
      if (pm != null && pm.currentTransaction().isActive()) {
        pm.currentTransaction().rollback();
      }
    }
  }

  private Object[] generatePersistentInstances() {
    StateTransitionObj[] objects = new StateTransitionObj[NUM_OBJECTS];
    try {
      Transaction t = pm.currentTransaction();
      t.begin();
      for (int i = 0; i < NUM_OBJECTS; ++i) {
        objects[i] = new StateTransitionObj(i);
        objects[i].writeField(i);
        pm.makePersistent(objects[i]);
      }
      t.commit();
      return objects;
    } finally {
      Transaction tx = pm.currentTransaction();
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }
}
