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

import java.util.Collection;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.jdo.Constants;
import javax.jdo.FetchGroup;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.datastore.DataStoreCache;
import javax.jdo.listener.InstanceLifecycleListener;
import javax.jdo.metadata.JDOMetadata;
import javax.jdo.metadata.TypeMetadata;

public class StubPMF implements PersistenceManagerFactory, Constants {

  private static final long serialVersionUID = 488698916248368422L;

  public static PersistenceManagerFactory getPersistenceManagerFactory(Map<?, ?> props) {

    StubPMF pmf = new StubPMF();

    pmf.setProperties(props);

    for (Object key : props.keySet()) {
      if (!(key instanceof String)) {
        continue;
      }
      String prop = (String) key;
      if (!prop.startsWith("javax.jdo.")) {
        continue;
      }
      pmf.setProperty(prop, props.get(prop));
    }

    return pmf;
  }

  public static PersistenceManagerFactory getPersistenceManagerFactory(
      Map<?, ?> overrides, Map<?, ?> props) {

    StubPMF pmf = new StubPMF();

    pmf.setProperties(props);
    pmf.setProperties(overrides);

    return pmf;
  }

  String name;
  String persistenceManagerFactoryClassName;
  String spiResourceName;
  String optionConnectionUserName;
  String optionConnectionPassword;
  String optionConnectionURL;
  String optionConnectionDriverName;
  String optionConnectionFactoryName;
  Object optionConnectionFactory;
  String optionConnectionFactory2Name;
  Object optionConnectionFactory2;
  boolean optionMultithreaded;
  String optionMapping;
  boolean optionOptimistic;
  boolean optionRetainValues;
  boolean optionRestoreValues;
  boolean optionNontransactionalRead;
  boolean optionNontransactionalWrite;
  boolean optionIgnoreCache;
  boolean optionDetachAllOnCommit;
  boolean optionCopyOnAttach;
  String optionName;
  String optionPersistenceUnitName;
  String optionServerTimeZoneID;
  String optionTransactionType;
  boolean optionReadOnly;
  String optionTransactionIsolationLevel;
  Integer optionDatastoreReadTimeoutMillis;
  Integer optionDatastoreWriteTimeoutMillis;

  final Properties properties = new Properties();

  public String getConnectionUserName() {
    return optionConnectionUserName;
  }

  public void setConnectionUserName(String connectionUserName) {
    this.optionConnectionUserName = connectionUserName;
  }

  public void setConnectionPassword(String connectionPassword) {
    this.optionConnectionPassword = connectionPassword;
  }

  public String getConnectionURL() {
    return optionConnectionURL;
  }

  public void setConnectionURL(String connectionURL) {
    this.optionConnectionURL = connectionURL;
  }

  public String getConnectionDriverName() {
    return optionConnectionDriverName;
  }

  public void setConnectionDriverName(String connectionDriverName) {
    this.optionConnectionDriverName = connectionDriverName;
  }

  public String getConnectionFactoryName() {
    return optionConnectionFactoryName;
  }

  public void setConnectionFactoryName(String connectionFactoryName) {
    this.optionConnectionFactoryName = connectionFactoryName;
  }

  public Object getConnectionFactory() {
    return optionConnectionFactory;
  }

  public void setConnectionFactory(Object connectionFactory) {
    this.optionConnectionFactory = connectionFactory;
  }

  public String getConnectionFactory2Name() {
    return optionConnectionFactory2Name;
  }

  public void setConnectionFactory2Name(String connectionFactory2Name) {
    this.optionConnectionFactory2Name = connectionFactory2Name;
  }

  public Object getConnectionFactory2() {
    return optionConnectionFactory2;
  }

  public void setConnectionFactory2(Object connectionFactory2) {
    this.optionConnectionFactory2 = connectionFactory2;
  }

  public boolean getMultithreaded() {
    return optionMultithreaded;
  }

  public void setMultithreaded(boolean multithreaded) {
    this.optionMultithreaded = multithreaded;
  }

  public String getMapping() {
    return optionMapping;
  }

  public void setMapping(String mapping) {
    this.optionMapping = mapping;
  }

  public boolean getOptimistic() {
    return optionOptimistic;
  }

  public void setOptimistic(boolean optimistic) {
    this.optionOptimistic = optimistic;
  }

  public boolean getRetainValues() {
    return optionRetainValues;
  }

  public void setRetainValues(boolean retainValues) {
    this.optionRetainValues = retainValues;
  }

  public boolean getRestoreValues() {
    return optionRestoreValues;
  }

  public void setRestoreValues(boolean restoreValues) {
    this.optionRestoreValues = restoreValues;
  }

  public boolean getNontransactionalRead() {
    return optionNontransactionalRead;
  }

  public void setNontransactionalRead(boolean nontransactionalRead) {
    this.optionNontransactionalRead = nontransactionalRead;
  }

  public boolean getNontransactionalWrite() {
    return optionNontransactionalWrite;
  }

  public void setNontransactionalWrite(boolean nontransactionalWrite) {
    this.optionNontransactionalWrite = nontransactionalWrite;
  }

  public boolean getIgnoreCache() {
    return optionIgnoreCache;
  }

  public void setIgnoreCache(boolean ignoreCache) {
    this.optionIgnoreCache = ignoreCache;
  }

  public boolean getDetachAllOnCommit() {
    return optionDetachAllOnCommit;
  }

  public void setDetachAllOnCommit(boolean detachAllOnCommit) {
    this.optionDetachAllOnCommit = detachAllOnCommit;
  }

  public boolean getCopyOnAttach() {
    return optionCopyOnAttach;
  }

  public void setCopyOnAttach(boolean copyOnAttach) {
    this.optionCopyOnAttach = copyOnAttach;
  }

  public String getName() {
    return optionName;
  }

  public void setName(String name) {
    this.optionName = name;
  }

  public String getPersistenceUnitName() {
    return optionPersistenceUnitName;
  }

  public void setPersistenceUnitName(String persistenceUnitName) {
    this.optionPersistenceUnitName = persistenceUnitName;
  }

  public String getServerTimeZoneID() {
    return optionServerTimeZoneID;
  }

  public void setServerTimeZoneID(String serverTimeZoneID) {
    this.optionServerTimeZoneID = serverTimeZoneID;
  }

  public String getTransactionType() {
    return optionTransactionType;
  }

  public void setTransactionType(String transactionType) {
    this.optionTransactionType = transactionType;
  }

  public boolean getReadOnly() {
    return optionReadOnly;
  }

  public void setReadOnly(boolean readOnly) {
    this.optionReadOnly = readOnly;
  }

  public String getTransactionIsolationLevel() {
    return optionTransactionIsolationLevel;
  }

  public void setTransactionIsolationLevel(String transactionIsolationLevel) {
    this.optionTransactionIsolationLevel = transactionIsolationLevel;
  }

  public Integer getDatastoreReadTimeoutMillis() {
    return optionDatastoreReadTimeoutMillis;
  }

  public void setDatastoreReadTimeoutMillis(Integer datastoreReadTimeoutMillis) {
    this.optionDatastoreReadTimeoutMillis = datastoreReadTimeoutMillis;
  }

  public Integer getDatastoreWriteTimeoutMillis() {
    return optionDatastoreWriteTimeoutMillis;
  }

  public void setDatastoreWriteTimeoutMillis(Integer datastoreWriteTimeoutMillis) {
    this.optionDatastoreWriteTimeoutMillis = datastoreWriteTimeoutMillis;
  }

  public void close() {
    throw new UnsupportedOperationException("not implemented");
  }

  public boolean isClosed() {
    return true;
  }

  public PersistenceManager getPersistenceManager() {
    throw new UnsupportedOperationException("not implemented");
  }

  public PersistenceManager getPersistenceManagerProxy() {
    throw new UnsupportedOperationException("not implemented");
  }

  public PersistenceManager getPersistenceManager(String userid, String password) {
    throw new UnsupportedOperationException("not implemented");
  }

  public Properties getProperties() {
    return properties;
  }

  public Collection<String> supportedOptions() {
    throw new UnsupportedOperationException("not implemented");
  }

  public DataStoreCache getDataStoreCache() {
    return new DataStoreCache() {

      public void evict(Object oid) {}

      public void evictAll() {}

      public void evictAll(Object... oids) {}

      public void evictAll(Collection<?> oids) {}

      public void evictAll(boolean subclasses, Class<?> pcClass) {}

      public void pin(Object oid) {}

      public void pinAll(Collection<?> oids) {}

      public void pinAll(Object... oids) {}

      public void pinAll(boolean subclasses, Class<?> pcClass) {}

      public void unpin(Object oid) {}

      public void unpinAll(Collection<?> oids) {}

      public void unpinAll(Object... oids) {}

      public void unpinAll(boolean subclasses, Class<?> pcClass) {}
    };
  }

  public void addInstanceLifecycleListener(InstanceLifecycleListener listener, Class<?>[] classes) {
    throw new UnsupportedOperationException("not implemented");
  }

  public void removeInstanceLifecycleListener(InstanceLifecycleListener listener) {
    throw new UnsupportedOperationException("not implemented");
  }

  public void addFetchGroups(FetchGroup... groups) {
    throw new UnsupportedOperationException("not implemented");
  }

  public void removeFetchGroups(FetchGroup... groups) {
    throw new UnsupportedOperationException("not implemented");
  }

  public void removeAllFetchGroups() {
    throw new UnsupportedOperationException("not implemented");
  }

  @SuppressWarnings("rawtypes")
  public FetchGroup getFetchGroup(Class cls, String name) {
    throw new UnsupportedOperationException("not implemented");
  }

  @SuppressWarnings("rawtypes")
  public Set<FetchGroup> getFetchGroups() {
    throw new UnsupportedOperationException("not implemented");
  }

  public void registerMetadata(JDOMetadata metadata) {
    throw new UnsupportedOperationException("not implemented");
  }

  public JDOMetadata newMetadata() {
    throw new UnsupportedOperationException("not implemented");
  }

  public TypeMetadata getMetadata(String className) {
    throw new UnsupportedOperationException("not implemented");
  }

  void setSpiResourceName(String spiPropertiesResourceName) {
    this.spiResourceName = spiPropertiesResourceName;
  }

  public String getSpiPropertiesResourceName() {
    return spiResourceName;
  }

  void setPersistenceManagerFactoryClass(String className) {
    this.persistenceManagerFactoryClassName = className;
  }

  public String getPersistenceManagerFactoryClass() {
    return this.persistenceManagerFactoryClassName;
  }

  void setProperty(String name, Object value) {
    String val = value.toString();

    if (name.equals(PROPERTY_PERSISTENCE_MANAGER_FACTORY_CLASS)) {
      setPersistenceManagerFactoryClass(val);
      return;
    }
    if (name.equals(PROPERTY_CONNECTION_DRIVER_NAME)) {
      setConnectionDriverName(val);
      return;
    }
    if (name.equals(PROPERTY_CONNECTION_FACTORY_NAME)) {
      setConnectionFactoryName(val);
      return;
    }
    if (name.equals(PROPERTY_CONNECTION_FACTORY2_NAME)) {
      setConnectionFactory2Name(val);
      return;
    }
    if (name.equals(PROPERTY_CONNECTION_PASSWORD)) {
      setConnectionPassword(val);
      return;
    }
    if (name.equals(PROPERTY_CONNECTION_URL)) {
      setConnectionURL(val);
      return;
    }
    if (name.equals(PROPERTY_CONNECTION_USER_NAME)) {
      setConnectionUserName(val);
      return;
    }
    if (name.equals(PROPERTY_IGNORE_CACHE)) {
      setCopyOnAttach(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_DATASTORE_READ_TIMEOUT_MILLIS)) {
      setDatastoreReadTimeoutMillis(Integer.parseInt(val));
      return;
    }
    if (name.equals(PROPERTY_DATASTORE_WRITE_TIMEOUT_MILLIS)) {
      setDatastoreWriteTimeoutMillis(Integer.parseInt(val));
      return;
    }
    if (name.equals(PROPERTY_DETACH_ALL_ON_COMMIT)) {
      setDetachAllOnCommit(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_IGNORE_CACHE)) {
      setIgnoreCache(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_MAPPING)) {
      setMapping(val);
      return;
    }
    if (name.equals(PROPERTY_MULTITHREADED)) {
      setMultithreaded(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_NAME)) {
      setName(val);
      return;
    }
    if (name.equals(PROPERTY_NONTRANSACTIONAL_READ)) {
      setNontransactionalRead(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_NONTRANSACTIONAL_WRITE)) {
      setNontransactionalWrite(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_OPTIMISTIC)) {
      setOptimistic(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_PERSISTENCE_UNIT_NAME)) {
      setPersistenceUnitName(val);
      return;
    }
    if (name.equals(PROPERTY_READONLY)) {
      setReadOnly(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_RESTORE_VALUES)) {
      setRestoreValues(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_RETAIN_VALUES)) {
      setRetainValues(Boolean.parseBoolean(val));
      return;
    }
    if (name.equals(PROPERTY_SERVER_TIME_ZONE_ID)) {
      setServerTimeZoneID(val);
      return;
    }
    if (name.equals(PROPERTY_TRANSACTION_ISOLATION_LEVEL)) {
      setTransactionIsolationLevel(val);
      return;
    }
    if (name.equals(PROPERTY_TRANSACTION_TYPE)) {
      setTransactionType(val);
      return;
    }
    if (name.equals(PROPERTY_SPI_RESOURCE_NAME)) {
      setSpiResourceName(val);
      return;
    }

    throw new IllegalArgumentException("unhandled stub PMF property " + name);
  }

  void setProperties(Map<?, ?> properties) {
    for (Object key : properties.keySet()) {
      String k = key.toString();
      Object v = properties.get(key);

      this.properties.put(k, v);
      setProperty(k, v);
    }
  }

  public Collection<Class> getManagedClasses() {
    throw new UnsupportedOperationException("not implemented");
  }
}
