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

import javax.jdo.JDODataStoreException;
import javax.jdo.JDOUserException;
import javax.jdo.Transaction;
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.pc.instancecallbacks.InstanceCallbackNonPersistFdsClass;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Calling InstanceCallbacks Postload Method <br>
 * <B>Keywords:</B> instancecallbacks <br>
 * <B>Assertion ID:</B> A10.1-1. <br>
 * <B>Assertion Description: </B> The <code>jdoPostLoad()</code> method of a class implementing
 * <code>InstanceCallbacks</code> is called after the default fetch group values are loaded from the
 * <code>StateManager</code> into the instance.
 */

/*
 *  Create a persistent object and commit().
 *
 *  Retrieve object in the next transaction and verify its state is hollow.
 *
 *  Reference a persistent attribute and verify:
 *     the call to jdoPostLoad() occurred just before this reference--and after the object was retrieved (via getObjectById()),
 *     jdoPostLoad() was called exactly once and
 *     once the attribute has been referenced, the state of the object is persistent-clean
 *
 *  Verify that the values of the persistent attributes available in jdoPostLoad() are the values actually in the object (the
 *    values have already been restored be the time jdoPostLoad() is called).
 */
public class CallingJdoPostload extends JDO_Test {

  /** */
  private static final String ASSERTION_FAILED = "Assertion A10.1-1 (CallingJdoPostload) 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(CallingJdoPostload.class);
  }

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

  /** */
  public void test() {
    pm = getPM();
    Transaction t = pm.currentTransaction();
    t.setRetainValues(false);

    InstanceCallbackNonPersistFdsClass.initializeStaticsForTest();

    t.begin();
    // create instance
    InstanceCallbackNonPersistFdsClass obj1 = new InstanceCallbackNonPersistFdsClass(2.2f, 13);
    pm.makePersistent(obj1);
    Object objPtr1 = pm.getObjectId(obj1);
    obj1.setNonPersist(1, (char) 2, 3.3, (short) 4);
    t.commit();

    t.begin();
    // set applicationStep before and after getObjectById() to be sure when jdoPostLoad() gets
    // called.
    InstanceCallbackNonPersistFdsClass.applicationStep =
        InstanceCallbackNonPersistFdsClass.beforeGetObjectById;
    try {
      obj1 =
          (InstanceCallbackNonPersistFdsClass)
              pm.getObjectById(objPtr1, true); // jdoPreLoad() called
    } catch (JDOUserException | JDODataStoreException e) {
      // could not locate persistent object created in previous transaction
      fail(
          ASSERTION_FAILED,
          "CallingJdoPostload:  Could not locate persistent object obj1 created in previous transaction "
              + e);
      return;
    }

    int objectState = currentState(obj1);
    // expect state to be hollow or persistent-clean
    if (objectState != HOLLOW && objectState != PERSISTENT_CLEAN) {
      fail(
          ASSERTION_FAILED,
          "State of object was not hollow or persistent clean after accessed via getObjectById((), state is "
              + states[objectState]);
    }

    InstanceCallbackNonPersistFdsClass.applicationStep =
        InstanceCallbackNonPersistFdsClass.afterGetObjectById;
    int getIntValue = obj1.intValue; // reference attribute in default fetch group
    objectState = currentState(obj1);

    // expect jdoPostLoad() was called
    if (!InstanceCallbackNonPersistFdsClass.postloadCalled) {
      fail(ASSERTION_FAILED, "jdoPostLoad() never called");
    }

    // only check other information if jdoPostLoad() called
    if (InstanceCallbackNonPersistFdsClass.postloadCalled) {
      // expect jdoPostLoad() was called only once
      if (InstanceCallbackNonPersistFdsClass.postloadCalledMultipleTimes) {
        fail(ASSERTION_FAILED, "jdoPostLoad was called more than once for the same loaded object");
      }

      // verify the value of intValue was available in jdoPostLoad()
      if (InstanceCallbackNonPersistFdsClass.savedIntValue != getIntValue) {
        fail(
            ASSERTION_FAILED,
            "intValue available in jdoPostLoad is incorrect.  It was "
                + InstanceCallbackNonPersistFdsClass.savedIntValue
                + ", it should be "
                + getIntValue);
      }

      // verify the value of floatValue was available in jdoPostLoad()
      if (InstanceCallbackNonPersistFdsClass.savedFloatValue != obj1.floatValue) {
        fail(
            ASSERTION_FAILED,
            "floatValue available in jdoPostLoad is incorrect.  It was "
                + InstanceCallbackNonPersistFdsClass.savedFloatValue
                + ", it should be "
                + obj1.floatValue);
      }
    }

    t.rollback();
    pm.close();
    pm = null;
  }
}
