/*
 * 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
 *
 *     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
 * 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);
    }
  }
}
