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

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.jdo.Constants;
import javax.jdo.PersistenceManager;
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Test GetProperties <br>
 * <B>Keywords:</B> getProperties getSupportedProperties setProperty <br>
 * <B>Assertion IDs:</B> <br>
 * <B>Assertion Description: </B>
 */
public class GetProperties extends JDO_Test implements Constants {

  /** */
  private static final String ASSERTION_FAILED_12_19_1 =
      "Assertion 12.19-1 setProperty() "
          + "If a vendor-specific property is not recognized, it is silently ignored.\n";

  private static final String ASSERTION_FAILED_12_19_2 =
      "Assertion 12.19-2 setProperty() If the value for the property is not supported by the implementation, "
          + "a JDOUserException is thrown.\n";
  private static final String ASSERTION_FAILED_12_19_3 =
      "Assertion 12.19-3 setProperty() "
          + "Property names might exactly match the names of the properties in javax.jdo.Constants "
          + "or might differ in case only.\n";
  private static final String ASSERTION_FAILED_12_19_4 =
      "Assertion 12.19-4 setProperty() "
          + "Properties of the transaction associated with a persistence manager "
          + "can be accessed via the named property in javax.jdo.Constants.\n";
  private static final String ASSERTION_FAILED_12_19_5 =
      "Assertion 12.19-5 getProperties() "
          + "getProperties() Return a map of String, "
          + "Object with the properties and values currently in effect.\n";
  private static final String ASSERTION_FAILED_12_19_6 =
      "Assertion 12.19-6 Changing the values in the map will not affect the properties in the PersistenceManager. ";
  private static final String ASSERTION_FAILED_12_19_7 =
      "Assertion 12.19-7 getSupportedProperties() Return the set of properties "
          + "supported by this PersistenceManager.\n";

  /**
   * 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(GetProperties.class);
  }

  @Override
  public void localSetUp() {
    getPM();
  }

  @Override
  public void localTearDown() {
    // the PM is left in an unknown state due to setting properties so it must be cleaned up
    cleanupPM();
  }

  private Collection<String> supportedOptions;
  private Set<String> supportedProperties;
  private static final Set<TestProperty> testRequiredProperties = new HashSet<>();
  private static final Map<String, Set<TestProperty>> testOptionalProperties = new HashMap<>();

  private interface TestProperty {
    void test(PersistenceManager pm, Set<String> supportedProperties);

    Object get(PersistenceManager pm);

    void set(PersistenceManager pm, Object value);

    void setMessageForNullResult(String messageForNullResult);

    void setMessageForWrongResultAfterSet(String messageForWrongResultAfterSet);
  }

  abstract class AbstractTestProperty implements TestProperty {
    final String propertyName;
    final Object testValue1;
    final Object testValue2;
    protected String messageForNullResult = ASSERTION_FAILED_12_19_5;
    protected String messageForWrongResultAfterSet = ASSERTION_FAILED_12_19_5;

    AbstractTestProperty(String propertyName, Object testValue1, Object testValue2) {
      this.propertyName = propertyName;
      this.testValue1 = testValue1;
      this.testValue2 = testValue2;
    }

    public void setMessageForNullResult(String messageForNullResult) {
      this.messageForNullResult = messageForNullResult;
    }

    public void setMessageForWrongResultAfterSet(String messageForWrongResultAfterSet) {
      this.messageForWrongResultAfterSet = messageForWrongResultAfterSet;
    }
  }

  /**
   * For each non-api supported property, getProperty(XXX) should return a value setProperty(XXX,
   * value1) should succeed getProperties() should return value1 setProperty(XXX, value2) should
   * succeed getProperties() should return value2
   */
  abstract class AbstractNonAPITestProperty extends AbstractTestProperty {
    AbstractNonAPITestProperty(String propertyName, Object testValue1, Object testValue2) {
      super(propertyName, testValue1, testValue2);
    }

    public Object get(PersistenceManager pm) {
      throw new RuntimeException("not implemented");
    }

    public void set(PersistenceManager pm, Object value) {
      throw new RuntimeException("not implemented");
    }

    public void test(PersistenceManager pm, Set<String> supportedProperties) {
      Object result0 = pm.getProperties().get(propertyName);
      errorIfEqual(
          this.messageForNullResult + "getProperties().get(" + propertyName + ")", null, result0);
      pm.setProperty(propertyName, testValue1);
      Object result1 = pm.getProperties().get(propertyName);
      errorIfNotEqual(
          this.messageForWrongResultAfterSet
              + "after pm.setProperty("
              + propertyName
              + ", "
              + testValue1
              + "), getProperties().get("
              + propertyName
              + ")",
          testValue1,
          result1);

      pm.setProperty(propertyName, testValue2);
      Object result2 = pm.getProperties().get(propertyName);
      errorIfNotEqual(
          this.messageForWrongResultAfterSet
              + "after pm.setProperty("
              + propertyName
              + ", "
              + testValue2
              + "), getProperties().get("
              + propertyName
              + ")",
          testValue2,
          result2);
    }
  }

  /**
   * For each api supported property, and for each of two values getProperty(XXX) should return a
   * value setProperty(XXX, value1) should succeed getXXX() should return value1 setXXX(value2)
   * should succeed getProperties() should return value2
   */
  abstract class AbstractAPITestProperty extends AbstractTestProperty {
    AbstractAPITestProperty(String propertyName, Object testValue1, Object testValue2) {
      super(propertyName, testValue1, testValue2);
    }

    public void test(PersistenceManager pm, Set<String> supportedProperties) {
      Object result0 = pm.getProperties().get(propertyName);
      errorIfEqual(
          this.messageForNullResult + "getProperties().get(" + propertyName + ")", null, result0);
      pm.setProperty(propertyName, testValue1);
      Object result1 = get(pm);
      errorIfNotEqual(
          this.messageForWrongResultAfterSet
              + "after pm.setProperty("
              + propertyName
              + ", "
              + testValue1
              + "), getXXX for "
              + propertyName,
          testValue1,
          result1);

      set(pm, testValue2);
      Object result2 = pm.getProperties().get(propertyName);
      errorIfNotEqual(
          this.messageForWrongResultAfterSet
              + "after pm.setXXX(), getProperties.get("
              + propertyName
              + ")",
          testValue2,
          result2);
    }
  }

  private final TestProperty testCopyOnAttach =
      new AbstractAPITestProperty(PROPERTY_COPY_ON_ATTACH, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.getCopyOnAttach();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.setCopyOnAttach((Boolean) value);
        }
      };

  private final TestProperty testDatastoreReadTimeoutMillis =
      new AbstractAPITestProperty(PROPERTY_DATASTORE_READ_TIMEOUT_MILLIS, 20, 40) {
        public Object get(PersistenceManager pm) {
          return pm.getDatastoreReadTimeoutMillis();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.setDatastoreReadTimeoutMillis((Integer) value);
        }
      };

  private final TestProperty testDatastoreWriteTimeoutMillis =
      new AbstractAPITestProperty(PROPERTY_DATASTORE_WRITE_TIMEOUT_MILLIS, 60, 80) {
        public Object get(PersistenceManager pm) {
          return pm.getDatastoreWriteTimeoutMillis();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.setDatastoreWriteTimeoutMillis((Integer) value);
        }
      };

  private final TestProperty testMultithreaded =
      new AbstractAPITestProperty(PROPERTY_MULTITHREADED, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.getMultithreaded();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.setMultithreaded((Boolean) value);
        }
      };

  private final TestProperty testLowerCaseMultithreaded =
      new AbstractAPITestProperty(PROPERTY_MULTITHREADED, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.getMultithreaded();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.setProperty("javax.jdo.option.multithreaded", value);
        }
      };

  private final TestProperty testUpperCaseMultithreaded =
      new AbstractAPITestProperty(PROPERTY_MULTITHREADED, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.getMultithreaded();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.setProperty("javax.jdo.option.MULTITHREADED", value);
        }
      };

  private final TestProperty testDetachAllOnCommit =
      new AbstractAPITestProperty(PROPERTY_DETACH_ALL_ON_COMMIT, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.getDetachAllOnCommit();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.setDetachAllOnCommit((Boolean) value);
        }
      };

  private final TestProperty testIgnoreCache =
      new AbstractAPITestProperty(PROPERTY_IGNORE_CACHE, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.getIgnoreCache();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.setIgnoreCache((Boolean) value);
        }
      };

  private final TestProperty testOptimistic =
      new AbstractAPITestProperty(PROPERTY_OPTIMISTIC, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.currentTransaction().getOptimistic();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.currentTransaction().setOptimistic((Boolean) value);
        }
      };

  private final TestProperty testRetainValues =
      new AbstractAPITestProperty(PROPERTY_RETAIN_VALUES, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.currentTransaction().getRetainValues();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.currentTransaction().setRetainValues((Boolean) value);
        }
      };

  private final TestProperty testRestoreValues =
      new AbstractAPITestProperty(PROPERTY_RESTORE_VALUES, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.currentTransaction().getRestoreValues();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.currentTransaction().setRestoreValues((Boolean) value);
        }
      };

  private final TestProperty testNontransactionalRead =
      new AbstractAPITestProperty(PROPERTY_NONTRANSACTIONAL_READ, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.currentTransaction().getNontransactionalRead();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.currentTransaction().setNontransactionalRead((Boolean) value);
        }
      };

  private final TestProperty testNontransactionalWrite =
      new AbstractAPITestProperty(PROPERTY_NONTRANSACTIONAL_WRITE, true, false) {
        public Object get(PersistenceManager pm) {
          return pm.currentTransaction().getNontransactionalWrite();
        }

        public void set(PersistenceManager pm, Object value) {
          pm.currentTransaction().setNontransactionalWrite((Boolean) value);
        }
      };

  private final TestProperty testIllegalArgument =
      new AbstractNonAPITestProperty(PROPERTY_IGNORE_CACHE, 1, false) {};

  private Set<TestProperty> setOf(TestProperty... testPropertys) {
    Set<TestProperty> result = new HashSet<>();
    for (TestProperty testProperty : testPropertys) {
      result.add(testProperty);
    }
    return result;
  }

  /** For each option supported by the PMF, test that the corresponding pm property is supported. */
  public void testGetSupportedProperties() {
    testRequiredProperties.add(testCopyOnAttach);
    testRequiredProperties.add(testDetachAllOnCommit);
    testRequiredProperties.add(testIgnoreCache);
    testRestoreValues.setMessageForWrongResultAfterSet(ASSERTION_FAILED_12_19_4);
    testRequiredProperties.add(testRestoreValues);

    testLowerCaseMultithreaded.setMessageForWrongResultAfterSet(ASSERTION_FAILED_12_19_3);
    testUpperCaseMultithreaded.setMessageForWrongResultAfterSet(ASSERTION_FAILED_12_19_3);
    testOptionalProperties.put(
        PROPERTY_MULTITHREADED,
        setOf(testMultithreaded, testLowerCaseMultithreaded, testUpperCaseMultithreaded));
    testOptionalProperties.put(
        OPTION_DATASTORE_TIMEOUT,
        setOf(testDatastoreReadTimeoutMillis, testDatastoreWriteTimeoutMillis));

    testOptimistic.setMessageForWrongResultAfterSet(ASSERTION_FAILED_12_19_4);
    testOptionalProperties.put(PROPERTY_OPTIMISTIC, setOf(testOptimistic));
    testRetainValues.setMessageForWrongResultAfterSet(ASSERTION_FAILED_12_19_4);
    testOptionalProperties.put(PROPERTY_RETAIN_VALUES, setOf(testRetainValues));
    testNontransactionalRead.setMessageForWrongResultAfterSet(ASSERTION_FAILED_12_19_4);
    testOptionalProperties.put(PROPERTY_NONTRANSACTIONAL_READ, setOf(testNontransactionalRead));
    testNontransactionalWrite.setMessageForWrongResultAfterSet(ASSERTION_FAILED_12_19_4);
    testOptionalProperties.put(PROPERTY_NONTRANSACTIONAL_WRITE, setOf(testNontransactionalWrite));

    supportedOptions = pmf.supportedOptions();
    for (String supportedOption : supportedOptions) {
      System.out.println("supportedOptions returned: " + supportedOption);
    }

    supportedProperties = pm.getSupportedProperties();
    errorIfEqual(ASSERTION_FAILED_12_19_7, null, supportedProperties);
    for (String supportedProperty : supportedProperties) {
      System.out.println("supportedProperties returned: " + supportedProperty);
    }

    // test required properties
    for (TestProperty testProperty : testRequiredProperties) {
      testProperty.test(pm, supportedProperties);
    }

    Set<Map.Entry<String, Object>> properties = pm.getProperties().entrySet();
    for (Map.Entry<String, Object> entry : properties) {
      System.out.println("getProperties returned: " + entry.getKey() + ": " + entry.getValue());
    }

    // for each supported option, test the corresponding supported property
    for (String supportedOption : supportedOptions) {
      Set<TestProperty> supportedOptionTestList = testOptionalProperties.get(supportedOption);
      if (supportedOptionTestList != null) {
        System.out.println("testing " + supportedOption);
        for (TestProperty supportedOptionTest : supportedOptionTestList) {
          supportedOptionTest.test(pm, supportedProperties);
        }
      }
    }

    try {
      testIllegalArgument.test(pm, supportedProperties);
      appendMessage(
          ASSERTION_FAILED_12_19_2
              + "setProperty(PROPERTY_IGNORE_CACHE, 1) failed: "
              + "Illegal argument PROPERTY_IGNORE_CACHE failed to throw an exception.");
    } catch (Throwable t) {
      // good catch
    }

    try {
      // unknown property should be ignored
      pm.setProperty("com.mystery.property", true);
    } catch (Throwable t) {
      appendMessage(ASSERTION_FAILED_12_19_1 + "Property com.mystery.property threw an exception.");
    }

    // changing a property of the returned set of property values must not change the underlying
    // property value
    pm.setProperty(PROPERTY_COPY_ON_ATTACH, true);
    Map<String, Object> props = pm.getProperties();
    props.put(PROPERTY_COPY_ON_ATTACH, false);
    errorIfNotEqual(ASSERTION_FAILED_12_19_6, true, pm.getCopyOnAttach());

    failOnError();
  }
}
