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.applib.annotation;
  
  import java.lang.annotation.ElementType;
  import java.lang.annotation.Inherited;
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  import java.lang.annotation.Target;
  import java.math.BigDecimal;
  import java.time.format.FormatStyle;
  import java.util.Locale;
  
  import jakarta.persistence.Column;
  
  import org.apache.causeway.applib.value.semantics.ValueSemanticsProvider;
  
  /**
   * Collects all the value-type specific customization attributes.
   *
   * @apiNote These are understood to be agnostic to the actual {@link Locale} in use.
   *
   * @see Action
   * @see Collection
   * @see Property
   * @see Parameter
   *
   * @since 2.x {@index}
   */
  @Inherited
  @Target({
      ElementType.METHOD,
      ElementType.FIELD,
      ElementType.TYPE,
      ElementType.PARAMETER,
      ElementType.ANNOTATION_TYPE,
  })
  @Retention(RetentionPolicy.RUNTIME)
  @Domain.Include // meta annotation, in support of meta-model validation
  public @interface ValueSemantics {
  
      /**
       * Allows to select {@link ValueSemanticsProvider}(s) by qualifier.
       *
       * @apiNote a single qualifier declared here must exactly match that of the
       * targeted {@link ValueSemanticsProvider} bean
       */
      String provider()
          default "";
  
      // -- NUMBER CONSTRAINTS
  
      /**
       * If associated with a {@link Number}, the maximum number of total digits accepted for
       * this number.<br>
       * Can be omitted, if {@link Column#precision()} is used.<br>
       * default = {@code 65}
       * @apiNote SQL's DECIMAL(precision, scale) has max-precision=65 and max-scale=30
       * @see Column#precision()
       */
      int maxTotalDigits()
          default 65;
  
      /**
       * If associated with a {@link Number}, the minimum number of integer digits required for
       * this number.<br>
       * default = {@code 1}
       */
      int minIntegerDigits()
          default 1;
  
      /**
       * If associated with a {@link BigDecimal}, the maximum number of fractional digits accepted
       * for this number.<br>
       * Can be omitted, if {@link Column#scale()} is used.<br>
       * default = {@code 30}
       * @apiNote SQL's DECIMAL(precision, scale) has max-precision=65 and max-scale=30
       * @see Column#scale()
       */
      int maxFractionalDigits()
          default 30;
  
      /**
       * If associated with a {@link BigDecimal}, the minimum number of fractional digits
       * required for this number.<br>
       * default = {@code 0}
       */
      int minFractionalDigits()
          default 0;
  
      // -- TEMPORAL FORMATTING
  
      /**
       * If associated with a temporal date value, the rendering style of a localized date.
       * @see FormatStyle
       */
      FormatStyle dateFormatStyle()
          default FormatStyle.MEDIUM;
  
      /**
       * If associated with a temporal time value, the rendering style of a localized time.
       * @see FormatStyle
       */
      FormatStyle timeFormatStyle()
          default FormatStyle.MEDIUM;
  
      /**
       * If associated with a temporal time value, the time of day precision,
       * used for editing a time field in the UI.<br>
       * default = {@link TimePrecision#SECOND}
       * @see TimePrecision
       */
      TimePrecision timePrecision()
          default TimePrecision.SECOND;
  
      /**
       * If associated with a temporal value,
       * that has time-zone or time-offset information,
       * the rendering mode, as to whether to transform the rendered value
       * to the user's local/current time-zone or not.<br>
       * default = {@link TimeZoneTranslation#TO_LOCAL_TIMEZONE}
       * @see TimeZoneTranslation
       */
      TimeZoneTranslation timeZoneTranslation()
          default TimeZoneTranslation.TO_LOCAL_TIMEZONE;
  
      /**
       * eg. &#64;ValueSemantics(dateRenderAdjustDays = ValueSemantics.AS_DAY_BEFORE)
       */
      public final static int AS_DAY_BEFORE = -1;
  
      /**
       * If associated with a date or date-time value,
       * instructs whether the date should be rendered as <i>n</i> days
       * after the actually stored date.
       * For negative <i>n</i> its days before respectively.
       *
       * <p>
       * This is intended to be used so that an exclusive end date of an interval
       * can be rendered as 1 day before the actual value stored.
       * </p>
       *
       * <p>
       * For example:
       * </p>
       * <pre>
       * public LocalDate getStartDate() { ... }
       *
       * &#64;ValueSemantics(dateRenderAdjustDays = ValueSemantics.AS_DAY_BEFORE)
       * public LocalDate getEndDate() { ... }
       * </pre>
       *
       * <p>
       * Here, the interval of the [1-may-2013,1-jun-2013) would be rendered as the dates
       * 1-may-2013 for the start date but using 31-may-2013 (the day before) for the end date.  What is stored
       * In the domain object, itself, however, the value stored is 1-jun-2013.
       * </p>
       */
      int dateRenderAdjustDays()
          default 0;
  }
  