/*
 * Copyright 2019 Immutables Authors and Contributors
 *
 * Licensed 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.immutables.criteria;


import org.immutables.value.Value;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.TimeZone;

@Value.Immutable
@Criteria
interface TypeHolder {

  // == primitives
  boolean booleanPrimitive();
  double doublePrimitive();
  float floatPrimitive();
  int intPrimitive();
  long longPrimitive();
  short shortPrimitive();
  byte bytePrimitive();
  char charPrimitive();

  // == boxed version of primitives
  Boolean booleanValue();
  Double doubleValue();
  Float floatValue();
  Integer intValue();
  Long longValue();
  Short shortValue();
  Byte byteValue();
  Character charValue();

  // == scalar optionals
  Optional<Boolean> optBoolean();
  OptionalDouble optDouble();
  Optional<Double> optDouble2();
  Optional<Float> optFloat();
  OptionalInt optInt();
  Optional<Integer> optInt2();
  OptionalLong optLong();
  Optional<Long> optLong2();
  Optional<Short> optShort();
  Optional<Byte> optByte();
  Optional<Character> optChar();

  // == lists
  List<Boolean> booleans();
  List<Double> doubles();
  List<Float> floats();
  List<Integer> integers();
  List<Long> longs();
  List<Short> shorts();
  List<Byte> bytes();
  List<Character> chars();

  // == arrays
  boolean[] booleanArray();
  double[] doubleArray();
  float[] floatArray();
  int[] integerArray();
  long[] longArray();
  short[] shortArray();
  byte[] byteArray();
  char[] charArray();

  enum Foo {
    ONE, TWO
  }

  Foo foo();
  Optional<Foo> optFoo();
  List<Foo> foos();
  Foo[] fooArray();

  // java.time.*
  LocalDate localDate();
  Optional<LocalDate> optLocalDate();
  List<LocalDate> localDates();
  LocalDate[] localDateArray();

  // java.util.Date
  java.util.Date utilDate();
  Optional<java.util.Date> optUtilDate();
  List<java.util.Date> utilDates();
  java.util.Date[] utilDateArray();

  // BigInteger and BigDecimal
  BigInteger bigInteger();
  Optional<BigInteger> optBigInteger();
  List<BigInteger> bigIntegers();
  BigInteger[] bigIntegerArray();

  BigDecimal bigDecimal();
  Optional<BigDecimal> optBigDecimal();
  List<BigDecimal> bigDecimals();
  BigDecimal[] bigDecimalArray();

  // TimeZone
  TimeZone timeZone();
  Optional<TimeZone> optTimeZone();
  List<TimeZone> timeZones();
  TimeZone[] timeZoneArray();

  // weird stuff
  Optional<Optional<String>> weird1();
  Optional<List<String>> weird2();
  List<Optional<String>> weird3();
  Optional<OptionalInt> weird4();
  Optional<Map<String, String>> weird5();

  Map<String, String> map();
  Optional<Map<String, String>> optionalMap();
  List<Map<String, String>> maps();

}

@@ -681,16 +681,50 @@
 Value;%0A%0A
+import javax.annotation.Nullable;%0A
 import j
@@ -740,24 +740,24 @@
 BigDecimal;%0A
-
 import java.
@@ -1484,24 +1484,364 @@
 arValue();%0A%0A
+  // == nullable version of boxed primitives%0A  @Nullable Boolean nullableBoolean();%0A  @Nullable Double nullableDouble();%0A  @Nullable Float nullableFloat();%0A  @Nullable Integer nullableInteger();%0A  @Nullable Long nullableLong();%0A  @Nullable Short nullableShort();%0A  @Nullable Byte nullableByte();%0A  @Nullable Character nullableCharacter();%0A%0A
   // == scal
@@ -2672,24 +2672,55 @@
 %3E optFoo();%0A
+  @Nullable Foo nullableFoo();%0A
   List%3CFoo%3E 
@@ -3151,24 +3151,69 @@
 gInteger();%0A
+  @Nullable BigInteger nullableBigInteger();%0A
   List%3CBigIn
@@ -3292,24 +3292,24 @@
 gDecimal();%0A
-
   Optional%3CB
@@ -3332,24 +3332,69 @@
 gDecimal();%0A
+  @Nullable BigDecimal nullableBigDecimal();%0A
   List%3CBigDe

Add @Nullable attributes to TypeHolder