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

import java.util.Date;
import java.util.Set;
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.pc.company.Address;
import org.apache.jdo.tck.pc.company.Company;
import org.apache.jdo.tck.pc.company.Department;
import org.apache.jdo.tck.pc.company.IDepartment;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> SecondClassObjectsTrackTheirChanges <br>
 * <B>Keywords:</B> embedded lifecycle <br>
 * <B>Assertion ID:</B> A14.6.9-9 <br>
 * <B>Assertion Description: </B> If an SCO field is in the result, the projected field is not owned
 * by any persistent instance, and modifying the SCO value has no effect on any persistent instance.
 * If an FCO field is in the result, the projected field is a persistent instance, and modifications
 * made to the instance are are reflected as changes to the datastore per transaction requirements.
 */
public class SecondClassObjectsTrackTheirChanges extends JDO_Test {

  /** */
  private static final String ASSERTION_FAILED =
      "Assertion A14.6.9-9 (SecondClassObjectsTrackTheirChanges) 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(SecondClassObjectsTrackTheirChanges.class);
  }

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

  /**
   * This tests that persistence-capable instances track changes or notify their owning instance
   * that they are dirty
   */
  public void testPCInstance() {
    pm = getPM();
    pm.currentTransaction().begin();
    Company comp = getPersistentNewInstance(0);
    pm.currentTransaction().commit(); // obj should transition to hollow
    testHollowInstance(comp);
    pm.currentTransaction().begin();
    makePersistentCleanInstance(comp);

    Address addr = (Address) comp.getAddress();
    // comp or addr should transition to persistent-dirty
    addr.setStreet("200 Orange Street");
    int currComp = currentState(comp);
    int currAddr = currentState(addr);
    if ((currComp != PERSISTENT_DIRTY) && (currAddr != PERSISTENT_DIRTY)) {
      fail(
          ASSERTION_FAILED,
          "Unable to create persistent-dirty instance "
              + "from persistent-clean instance via changing Address instance, "
              + "state of Company instance is "
              + states[currComp]
              + " and state of Address instance is "
              + states[currAddr]);
    }
  }

  /**
   * This tests that mutable system class instances track changes or notify their owning instance
   * that they are dirty
   */
  public void testMutableSystemClass() {
    pm = getPM();
    pm.currentTransaction().begin();
    Company comp = getPersistentNewInstance(1);
    pm.currentTransaction().commit(); // obj should transition to hollow
    testHollowInstance(comp);
    pm.currentTransaction().begin();
    makePersistentCleanInstance(comp);

    Set<IDepartment> depts = comp.getDepartments();
    // comp or depts should transition to persistent-dirty
    comp.addDepartment(new Department(0, "HR", comp));
    int currComp = currentState(comp);
    int currDepts = currentState(depts);
    if ((currComp != PERSISTENT_DIRTY) && (currDepts != PERSISTENT_DIRTY)) {
      fail(
          ASSERTION_FAILED,
          "Unable to create persistent-dirty instance "
              + "from persistent-clean instance via changing Departments "
              + "instance, state of Company instance is "
              + states[currComp]
              + " and state of Departments instance is "
              + states[currDepts]);
    }
  }

  public Company getPersistentNewInstance(long companyid) {
    Company obj =
        new Company(companyid, "MyCompany", new Date(), new Address(0, "", "", "", "", ""));
    pm.makePersistent(obj); // obj should transition to persistent-new
    int curr = currentState(obj);
    if (curr != PERSISTENT_NEW) {
      fail(
          ASSERTION_FAILED,
          "Unable to create persistent-new instance "
              + "from transient instance via makePersistent(), state is "
              + states[curr]);
    }
    return obj;
  }

  public void testHollowInstance(Company obj) {
    int curr = currentState(obj);
    if (curr != HOLLOW) {
      fail(
          ASSERTION_FAILED,
          "Unable to create hollow instance "
              + "from persistent-new instance via commit(), state is "
              + states[curr]);
    }
  }

  public void makePersistentCleanInstance(Company obj) {
    pm.makeTransactional(obj); // obj should transition to persistent-clean
    int curr = currentState(obj);
    if (curr != PERSISTENT_CLEAN) {
      fail(
          ASSERTION_FAILED,
          "Unable to create persistent-clean instance "
              + "from hollow instance via makeTransactional(obj), state is "
              + states[curr]);
    }
  }
}
