/*
 * 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 java.util.Date;
import java.util.Set;
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.InstanceCallbackClass;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> No Access To Fields After Predelete <br>
 * <B>Keywords:</B> instancecallbacks <br>
 * <B>Assertion ID:</B> A10.4-3. <br>
 * <B>Assertion Description: </B> Access to field values after a call to <code>jdoPreDelete()</code>
 * of a class implementing <code>InstanceCallbacks</code> are disallowed.
 */

/*
 *  Delete a persistent object and new object.  While the objects are in state persitent-deleted (or persistent-new-deleted)
 *     access persistent fields (except do not reference primary key fields).
 *
 *  Verify the field access results in a JDOUserException.
 */

public class NoAccessToFieldsAfterPredelete extends JDO_Test {

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

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

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

    InstanceCallbackClass.initializeStaticsForTest();

    t.begin();
    // make intValue outside the range of zero to arraySize-1 to skip most jdoPreDelete() code.
    InstanceCallbackClass a =
        new InstanceCallbackClass(
            "object a", null, InstanceCallbackClass.arraySize, 6.0, (short) -1, '6', null);
    pm.makePersistent(a);
    Object aId = pm.getObjectId(a);
    t.commit();

    t.begin();
    // relocte object.
    try {
      a = (InstanceCallbackClass) pm.getObjectById(aId, true);
    } catch (JDOUserException | JDODataStoreException e) {
      fail(
          ASSERTION_FAILED,
          "NoAccessToFieldsAfterPredelete:  Could not locate persistent object created in previous transaction, got "
              + e);
      return;
    }

    pm.deletePersistent(a);
    performAccessFieldTests("Object in state persistent-deleted:  ", a);

    InstanceCallbackClass b =
        new InstanceCallbackClass(
            "object b", null, InstanceCallbackClass.arraySize + 1, 7.0, (short) -1, '7', null);
    pm.makePersistent(b);
    pm.deletePersistent(b);
    performAccessFieldTests("Object in state persistent-new-deleted:  ", b);

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

  /** */
  void performAccessFieldTests(String title, InstanceCallbackClass o) {
    try {
      short x1 = o.childToDelete;
      // http://issues.apache.org/jira/browse/JDO-413
      // fail(ASSERTION_FAILED, title + "Accessed persistent short field childToDelete--should have
      // gotten JDOUserException");
    } catch (JDOUserException e) {
      // expected
    }

    try {
      double x2 = o.doubleValue;
      // http://issues.apache.org/jira/browse/JDO-413
      // fail(ASSERTION_FAILED, title + "Accessed persistent double field doubleValue--should have
      // gotten JDOUserException");
    } catch (JDOUserException e) {
      // expected
    }

    try {
      char x3 = o.charValue;
      // http://issues.apache.org/jira/browse/JDO-413
      // fail(ASSERTION_FAILED, title + "Accessed persistent char field charValue--should have
      // gotten JDOUserException");
    } catch (JDOUserException e) {
      // expected
    }

    try {
      String x4 = o.name;
      // http://issues.apache.org/jira/browse/JDO-413
      // fail(ASSERTION_FAILED,title + "Accessed persistent String field name--should have gotten
      // JDOUserException");
    } catch (JDOUserException e) {
      // expected
    }

    try {
      Date x5 = o.timeStamp;
      // http://issues.apache.org/jira/browse/JDO-413
      // fail(ASSERTION_FAILED, title + "Accessed persistent Date field timeStamp--should have
      // gotten JDOUserException");
    } catch (JDOUserException e) {
      // expected
    }

    try {
      Set<InstanceCallbackClass> x6 = o.children;
      // http://issues.apache.org/jira/browse/JDO-413
      // fail(ASSERTION_FAILED, title + "Accessed persistent HashSet field Children--should have
      // gotten JDOUserException");
    } catch (JDOUserException e) {
      // expected
    }

    try {
      InstanceCallbackClass x7 = o.nextObj;
      // http://issues.apache.org/jira/browse/JDO-413
      // fail(ASSERTION_FAILED, title + "Accessed persistent InstanceCallbackClass reference field
      // nextObj--should have gotten JDOUserException");
    } catch (JDOUserException e) {
      // expected
    }
  }
}
