/*
 * 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
 *
 *     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
 * limitations under the License.
 */

package javax.jdo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.jdo.spi.PersistenceCapable;
import javax.jdo.util.AbstractTest;
import javax.jdo.util.BatchTestRunner;

/*
 * ObjectStateTest.java
 * This test class verifies the proper returned ObjectState for
 * each life cycle state. See Table 3 in section 7.4.
 *
 * @since 2.1
 */
public class ObjectStateTest extends AbstractTest {

  static final int PERSISTENT = 1;
  static final int TRANSACTIONAL = 2;
  static final int DIRTY = 4;
  static final int NEW = 8;
  static final int DELETED = 16;
  static final int DETACHED = 32;

  private static final Method jdoIsPersistent =
      getDeclaredMethod(PersistenceCapable.class, "jdoIsPersistent", null);
  private static final Method jdoIsTransactional =
      getDeclaredMethod(PersistenceCapable.class, "jdoIsTransactional", null);
  private static final Method jdoIsDirty =
      getDeclaredMethod(PersistenceCapable.class, "jdoIsDirty", null);
  private static final Method jdoIsNew =
      getDeclaredMethod(PersistenceCapable.class, "jdoIsNew", null);
  private static final Method jdoIsDeleted =
      getDeclaredMethod(PersistenceCapable.class, "jdoIsDeleted", null);
  private static final Method jdoIsDetached =
      getDeclaredMethod(PersistenceCapable.class, "jdoIsDetached", null);

  /** */
  public static void main(String args[]) {
    BatchTestRunner.run(ObjectStateTest.class);
  }

  public void testNull() {
    PersistenceCapable mock = null;
    assertObjectState("null", null, mock);
  }

  public void testTransient() {
    PersistenceCapable mock = newMock(0);
    assertObjectState("transient", ObjectState.TRANSIENT, mock);
  }

  public void testTransientClean() {
    PersistenceCapable mock = newMock(TRANSACTIONAL);
    assertObjectState("transient-clean", ObjectState.TRANSIENT_CLEAN, mock);
  }

  public void testTransientDirty() {
    PersistenceCapable mock = newMock(TRANSACTIONAL + DIRTY);
    assertObjectState("transient-dirty", ObjectState.TRANSIENT_DIRTY, mock);
  }

  public void testPersistentNew() {
    PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL + NEW + DIRTY);
    assertObjectState("persistent-new", ObjectState.PERSISTENT_NEW, mock);
  }

  public void testPersistentNontransactional() {
    PersistenceCapable mock = newMock(PERSISTENT);
    assertObjectState(
        "persistent-nontransactional", ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, mock);
  }

  public void testPersistentNontransactionalDirty() {
    PersistenceCapable mock = newMock(PERSISTENT + DIRTY);
    assertObjectState(
        "persistent-nontransactional-dirty", ObjectState.PERSISTENT_NONTRANSACTIONAL_DIRTY, mock);
  }

  public void testPersistentClean() {
    PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL);
    assertObjectState("persistent-clean", ObjectState.PERSISTENT_CLEAN, mock);
  }

  public void testPersistentDirty() {
    PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL + DIRTY);
    assertObjectState("persistent-dirty", ObjectState.PERSISTENT_DIRTY, mock);
  }

  public void testPersistentDeleted() {
    PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL + DIRTY + DELETED);
    assertObjectState("persistent-deleted", ObjectState.PERSISTENT_DELETED, mock);
  }

  public void testPersistentNewDeleted() {
    PersistenceCapable mock = newMock(PERSISTENT + TRANSACTIONAL + NEW + DIRTY + DELETED);
    assertObjectState("persistent-new-deleted", ObjectState.PERSISTENT_NEW_DELETED, mock);
  }

  public void testDetachedClean() {
    PersistenceCapable mock = newMock(DETACHED);
    assertObjectState("detached-clean", ObjectState.DETACHED_CLEAN, mock);
  }

  public void testDetachedDirty() {
    PersistenceCapable mock = newMock(DETACHED + DIRTY);
    assertObjectState("detached-dirty", ObjectState.DETACHED_DIRTY, mock);
  }

  private void assertObjectState(String string, ObjectState expected, PersistenceCapable pc) {
    ObjectState actual = JDOHelper.getObjectState(pc);
    // test for == here because enums should be singleton
    if (actual == expected) return;
    fail(
        "ObjectState failure for " + string + NL + "expected: " + expected + ", actual: " + actual);
  }

  /**
   * Construct a new mock instance of PersistenceCapable that responds to methods jdoIsXXX by
   * returning the bit value of its constructor masked with the value of XXX.
   *
   * @param i the sum of bit masks representing the life cycle state
   * @return a mock instance of PersistenceCapable
   */
  private PersistenceCapable newMock(final int i) {
    return (PersistenceCapable)
        Proxy.newProxyInstance(
            PersistenceCapable.class.getClassLoader(),
            new Class[] {PersistenceCapable.class},
            new MockInvocationHandler(i));
  }

  private class MockInvocationHandler implements InvocationHandler {
    /** States is the sum of all life cycle interrogatives. */
    private final int states;

    /**
     * Constructs an invocation handler with the specified bit fields set according to the sum of
     * values of PERSISTENT, TRANSACTIONAL, DIRTY, NEW, DELETED, and DETACHED.
     *
     * @param i the bit field values for the life cycle interrogatives
     */
    private MockInvocationHandler(int i) {
      states = i;
    }

    /**
     * @param object the PersistenceCapable instance
     * @param method the method being invoked
     * @param parameters parameters (should be null)
     * @throws java.lang.Throwable unused
     * @return for jdoIsXXX methods only, returns whether the bit field selected by the method is
     *     set in the mock handler
     */
    public Object invoke(Object object, Method method, Object[] parameters) throws Throwable {
      if (method.equals(jdoIsPersistent)) {
        return (0 != (states & PERSISTENT));
      }
      if (method.equals(jdoIsTransactional)) {
        return (0 != (states & TRANSACTIONAL));
      }
      if (method.equals(jdoIsDirty)) {
        return (0 != (states & DIRTY));
      }
      if (method.equals(jdoIsNew)) {
        return (0 != (states & NEW));
      }
      if (method.equals(jdoIsDeleted)) {
        return (0 != (states & DELETED));
      }
      if (method.equals(jdoIsDetached)) {
        return (0 != (states & DETACHED));
      }
      fail("Unexpected method called: " + method.getName());
      return Boolean.FALSE; // not reached
    }
  }

  private static Method getDeclaredMethod(
      Class<?> clazz, String methodName, Class<?>[] parameters) {
    try {
      @SuppressWarnings("unchecked")
      Method result = clazz.getDeclaredMethod(methodName, parameters);
      return result;
    } catch (Exception ex) {
      // human-readable class.methodName(parameter[,parameter])
      StringBuffer sb = new StringBuffer(methodName);
      String delimiter = "(";
      for (Class<?> parameter : parameters) {
        sb.append(delimiter);
        sb.append(parameter.getName());
        delimiter = ",";
      }
      sb.append(")");
      throw new RuntimeException(
          "getDeclaredMethod for " + clazz.getName() + "." + sb + " threw..." + ex);
    }
  }
}
