content: /*
   *  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 org.apache.causeway.core.config;
  
  import org.springframework.boot.context.properties.ConfigurationProperties;
  import org.springframework.validation.annotation.Validated;
  
  import lombok.Data;
  
  /**
   * Selected configuration for Eclipselink, to provide IDE support.
   *
   * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm">Eclipselink Config Property docs</a>
   */
  @ConfigurationProperties("eclipselink")
  @Data
  @Validated
  public class EclipselinkConfiguration {
  
      /**
       * Options are
       * <ul>
       * <li>true: Weave the entity classes dynamically.</li>
       * <li>false: Do not weave the entity classes.</li>
       * <li>static: Weave the entity classes statically.</li>
       * </ul>
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#weaving">eclipse.weaving</a>
       */
      private String weaving = "false";
  
      @ConfigurationProperties("eclipselink.weaving")
      @Validated
      @Data
      public static class Weaving {
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDCEEFC">eclipse.weaving.changetracking</a>
           */
          private boolean changetracking = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BABGGCGC">eclipse.weaving.eager</a>
           */
          private boolean eager = false;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDDIFGE">eclipse.weaving.fetchgroups</a>
           */
          private boolean fetchgroups = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BABJICDJ">eclipse.weaving.internal</a>
           */
          private boolean internal = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BABDBIFE">eclipse.weaving.lazy</a>
           */
          private boolean lazy = true;
      }
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#delayonstartup">eclipselink.deploy-on-startup</a>
       */
      private boolean deployOnStartup = false;
  
      private final Descriptor descriptor = new Descriptor();
      @Data
      public static class Descriptor {
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CCHIEAIA">eclipselink.descriptor.customizer</a>
           */
          @CausewayConfiguration.AssignableFrom("org.eclipse.persistence.descriptors.ClassDescriptor")
          Class<?> customizer = null;
      }
  
      private final Session session = new Session();
      @Data
      public static class Session {
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#session.customizer">eclipselink.session.customizer</a>
           */
          @CausewayConfiguration.AssignableFrom("org.eclipse.persistence.config.SessionCustomizer")
          Class<?> customizer = null;
  
          private final Include include = new Include();
          @Data
          public static class Include {
              private final Descriptor descriptor = new Descriptor();
              @Data
              public static class Descriptor {
  
                  /**
                   * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDFDJJD">eclipselink.session.include.descriptor.queries</a>
                   */
                  private boolean queries = false;
              }
          }
      }
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#session-event-listener">eclipselink.session-event-listener</a>
       */
      @CausewayConfiguration.AssignableFrom("org.eclipse.persistence.sessions.SessionEventListener")
      Class<?> sessionEventListener = null;
  
      private final Logging logging = new Logging();
      @Data
      public static class Logging {
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDJCBIF">eclipselink.logging.connection</a>
           */
          private boolean connection = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BEIFJBIE">eclipselink.logging.exceptions</a>
           */
          private boolean exceptions = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BEIHGBBC">eclipselink.logging.file</a>
           */
          private String file = null;
  
          public enum LoggingLevel {
              OFF,
              SEVERE,
              WARNING,
              INFO,
              CONFIG,
              FINE,
              FINER,
              FINEST,
              ALL
          }
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDGFDDH">eclipselink.logging.level</a>
           */
          private LoggingLevel level = LoggingLevel.INFO;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BEIHGGHH">eclipselink.logging.session</a>
           */
          private boolean session = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BEIFFGGB">eclipselink.logging.thread</a>
           */
          private boolean thread = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BEIJCEBJ">eclipselink.logging.timestamp</a>
           */
          private boolean timestamp = true;
      }
  
      private final Cache cache = new Cache();
      @Data
      public static class Cache {
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CCHEEFGA">eclipselink.cache.database-event-listener</a>
           */
          @CausewayConfiguration.AssignableFrom("org.eclipse.persistence.platform.database.events.DatabaseEventListener")
          Class<?> databaseEventListener;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDEJCJJ">eclipselink.cache.shared</a>
           */
          boolean shared = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDIGIEC">eclipselink.cache.size</a>
           */
          int size = 100; // bytes
  
          /**
           * The CacheType enum is used with the Cache annotation for a persistent class.
           * It defines the type of cache (IdentityMap) used for the class. By default the
           * SOFT_WEAK cache type is used.
           *
           * @see org.eclipse.persistence.annotations.Cache
           * @author Guy Pelletier
           * @since Oracle TopLink 11.1.1.0.0
           */
          public enum CacheType {
              /**
               * Provides full caching and guaranteed identity. Caches all objects
               * and does not remove them.
               * WARNING: This method may be memory intensive when many objects are
               * read.  If used on a large data set it will eventually causes an out of memory error.
               */
              Full,
  
              /**
               * Similar to the FULL identity map except that the map holds the
               * objects using weak references. This method allows full garbage
               * collection and guaranteed identity.  It will only hold objects
               * that are referenced by the application so may not provide a large caching benefit.
               */
              Weak,
  
              /**
               * Similar to the FULL identity map except that the map holds the
               * objects using soft references. This method allows full garbage
               * collection when memory is low and provides full caching and guaranteed identity.
               */
              Soft,
  
              /**
               * Similar to the WEAK identity map except that it maintains a
               * most-frequently-used sub-cache. The size of the sub-cache is
               * proportional to the size of the identity map as specified by
               * {@literal @}Cache size attribute. The sub-cache
               * uses soft references to ensure that these objects are
               * garbage-collected only if the system is low on memory.
               */
              SoftWeak,
  
              /**
               * Identical to the soft cache weak (SOFT_WEAK) identity map except
               * that it uses hard references in the sub-cache. Use this identity
               * map if soft references do not behave properly on your platform.
               */
              HardWeak,
  
              /**
               * WARNING: Does not preserve object identity and does not cache
               * objects.  This cache type is not recommend and should normally not be used.
               * This cache type should not be used to disable caching, to properly disable
               * caching set the @Cache isolation attribute to ISOLATED.
               */
              NONE
          }
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDGDIEI">eclipselink.cache.type</a>
           */
          CacheType type = CacheType.SoftWeak;
      }
  
      private final FlushClear flushClear = new FlushClear();
      @Data
      public static class FlushClear {
  
          /**
           * FlushClearCache persistence property
           * defines modes of cache handling after em.flush call followed by em.clear call.
           * This property could be specified while creating either EntityManagerFactory
           * (createEntityManagerFactory or persistence.xml)
           * or EntityManager (createEntityManager); the latter overrides the former.
           *
           * <p>JPA persistence property Usage:
           *
           * <p><code>properties.add(PersistenceUnitProperties.FLUSH_CLEAR_CACHE, FlushClearCache.Drop);</code>
           *
           * <p>Values are case-insensitive.
           * "" could be used instead of default value FlushClearCache.DEFAULT.
           */
          public enum FlushClearCache {
  
              /**
               * Call to clear method causes to drop from EntityManager cache only the objects that haven't been flushed.
               * This is the most accurate mode: shared cache is perfect after commit;
               * but the least memory effective: smbd repeatedly using flush followed by clear
               * may eventually run out of memory in a huge transaction.
               */
              Merge,
  
              /**
               * Call to clear method causes to drop the whole EntityManager cache.
               * This is the fasteset and using the least memory mode -
               * but after commit the shared cache potentially contains stale data.
               */
              Drop,
  
              /** Call to clear method causes to drops the whole EntityManager cache,
               * on commit the classes that have at least one object updated or deleted
               * are invalidated in the shared cache.
               * This is a compromise mode: potentially a bit slower than drop,
               * but has virtually the same memory efficiency.
               * After commit all potentially stale data is invalidated in the shared cache.
               */
              DropInvalidate,
          }
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CDEJGBEI">eclipselink.flush-clear.cache</a>
           */
          FlushClearCache cache = FlushClearCache.DropInvalidate;
      }
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#createddljdbcfilename">eclipselink.create-ddl-jdbc-file-name</a>
       */
      String createDdlJdbcFileName = null;
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BABFEBCG">eclipselink.drop-ddl-jdbc-file-name</a>
       */
      String dropDdlJdbcFileName = null;
  
      private final Ddl ddl = new Ddl();
      @Data
      public static class Ddl {
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BEHBIEJG">eclipselink.ddl.table-creation-suffix</a>
           */
          String tableCreationSuffix = null;
      }
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BABHEJJI">eclipselink.ddl-generation</a>
       */
      @CausewayConfiguration.OneOf(value={"create-tables", "create-or-extend-tables", "drop-and-create-tables", "none"})
      String ddlGeneration = "none";
  
      @ConfigurationProperties("eclipselink.ddl-generation")
      @Validated
      @Data
      public static class DdlGeneration {
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#BABCDHBB">eclipselink.ddl-generation.output-mode</a>
           */
          @CausewayConfiguration.OneOf(value={"both", "database", "sql-script"})
          String outputMode = "database";
  
      }
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CCHCJCDJ">eclipselink.exception-handler</a>
       */
      @CausewayConfiguration.AssignableFrom("org.eclipse.persistence.exceptions.ExceptionHandler")
      Class<?> exceptionHandler = null;
  
      /**
       * The "<code>eclipselink.profiler</code>" property configures the type of
       * profiler used to capture runtime statistics.
       * <p>
       * <b>Allowed Values:</b>
       * <ul>
       * <li>"<code>NoProfiler</code>" (DEFAULT)
       * <li>"<code>PerformanceMonitor</code>" - use {@link org.eclipse.persistence.tools.profiler.PerformanceMonitor}
       * <li>"<code>PerformanceProfiler</code>" - use {@link org.eclipse.persistence.tools.profiler.PerformanceProfiler}
       * <li>"<code>QueryMonitor</code>" - use {@link org.eclipse.persistence.tools.profiler.QueryMonitor}
       * <li>"<code>DMSProfiler</code>" - use {@link org.eclipse.persistence.tools.profiler.oracle.DMSPerformanceProfiler}
       * <li>the fully qualified name for a class that implements {@link org.eclipse.persistence.sessions.SessionProfiler} interface
       * </ul>
       *
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#profiler">eclipselink.profiler</a>
       */
      private String profiler = "NoProfiler";
  
      private final Jdbc jdbc = new Jdbc();
      @Data
      public static class Jdbc {
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CIHHJBFB">eclipselink.jdbc.allow-native-sql-queries</a>
           */
          private boolean allowNativeSqlQueries = true;
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CIHIAGAF">eclipselink.jdbc.batch-writing</a>
           */
          @CausewayConfiguration.OneOf(value={"jdbc", "buffered", "oracle-jdbc", "none"})
          String batchWriting = "none";
  
          @ConfigurationProperties("eclipselink.jdbc.batch-writing")
          @Validated
          @Data
          public static class BatchWriting {
  
              /**
               * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CIHJADHF">eclipse.jdbc.batchwriting.size</a>
               */
              private int size;
          }
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDHAFAA">eclipselink.jdbc.cache-statements</a>
           */
          private boolean cacheStatements = true;
  
          @ConfigurationProperties("eclipselink.jdbc.cache-statements")
          @Validated
          @Data
          public static class CacheStatements {
  
              /**
               * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CACBICGG">eclipse.jdbc.cache-statements.size</a>
               */
              private int size;
          }
  
          /**
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm">eclipselink.jdbc.native-sql</a>
           */
          private boolean nativeSql = true;
  
      }
  
      private final Concurrency concurrency = new Concurrency();
      @Data
      public static class Concurrency {
  
          private final Manager manager = new Manager();
          @Data
          public static class Manager {
  
              /**
               * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#concurrency.manager.waittime">eclipselink.concurrency.manager.waittime</a>
               */
              private long waittime = 0; // ms
  
              /**
               * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#concurrency.manager.maxsleeptime">eclipselink.concurrency.manager.maxsleeptime</a>
               */
              private long maxsleeptime = 40000; // ms
  
              /**
               * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#concurrency.manager.maxfrequencytodumptinymessage">eclipselink.concurrency.manager.maxfrequencytodumptinymessage</a>
               */
              private long maxfrequencytodumptinymessage = 40000; // ms
  
              /**
               * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#concurrency.manager.maxfrequencytodumptinymessage">eclipselink.concurrency.manager.maxfrequencytodumpmassivemessage</a>
               */
              private long maxfrequencytodumpmassivemessage = 60000; // ms
  
              private final Allow allow = new Allow();
              @Data
              public static class Allow {
  
                  /**
                   * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#concurrency.manager.allow.interruptedexception">eclipselink.concurrency.manager.allow.interruptedexception</a>
                   */
                  private boolean interruptedexception = true;
  
                  /**
                   * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#concurrency.manager.allow.concurrencyexception">eclipselink.concurrency.manager.allow.concurrencyexception</a>
                   */
                  private boolean concurrencyexception = true;
  
                  /**
                   * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#concurrency.manager.allow.readlockstacktrace">eclipselink.concurrency.manager.allow.readlockstacktrace</a>
                   */
                  private boolean readlockstacktrace = true;
              }
          }
      }
  
      public enum IdValidation {
          /**
           * Null, 0 and negative values are invalid for IDs extending Number and primitive int and long IDs.
           */
          Negative,
          /**
           * EclipseLink performs no ID validation.
           */
          None,
          /**
           * Null is invalid All other values are valid.
           */
          Null,
          /**
           * Null, 0 and negative values are invalid for primitive int and long IDs.
           */
          Zero
      }
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CACEEGCC">eclipselink.id-validation</a>
       */
      private IdValidation idValidation = IdValidation.None;
  
      private final Jpa jpa = new Jpa();
      @Data
      public static class Jpa {
          /**
           * Specify JPA processing to uppercase all column name definitions (simulating case insensitivity).
           *
           * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDJGCBD">eclipselink.jpa.uppercase-column-names</a>
           */
          private boolean upperCaseColumnNames = false;
      }
  
      private final Jpql jpql = new Jpql();
      @Data
      public static class Jpql {
  
          @CausewayConfiguration.OneOf(value={"EclipseLink", "JPA 1.0", "JPA 2.0", "JPA 2.1", "None"})
          private String validation = "EclipseLink";
      }
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#CHDHBGIE">eclipselink.tenant-id</a>
       */
      private String tenantId;
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#validate-existence">eclipselink.validate-existence</a>
       */
      private boolean validateExistence = false;
  
      /**
       * @see <a href="https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/persistenceproperties_ref.htm#validation-only">eclipselink.validation-only</a>
       */
      private boolean validationOnly = false;
  
  }
  