gt:                 if (foundField != null) {
context: /*-
   * See the file LICENSE for redistribution information.
   *
   * Copyright (c) 2002, 2015 Oracle and/or its affiliates.  All rights reserved.
   *
   */
  
  package com.sleepycat.persist.model;
  
  import java.lang.reflect.Field;
  import java.lang.reflect.Modifier;
  import java.lang.reflect.ParameterizedType;
  import java.lang.reflect.Type;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
  
  import com.sleepycat.compat.DbCompat;
  
  /**
   * The default annotation-based entity model.  An <code>AnnotationModel</code>
   * is based on annotations that are specified for entity classes and their key
   * fields.
   *
   * <p>{@code AnnotationModel} objects are thread-safe.  Multiple threads may
   * safely call the methods of a shared {@code AnnotationModel} object.</p>
   *
   * <p>The set of persistent classes in the annotation model is the set of all
   * classes with the {@link Persistent} or {@link Entity} annotation.</p>
   *
   * <p>The annotations used to define persistent classes are: {@link Entity},
   * {@link Persistent}, {@link PrimaryKey}, {@link SecondaryKey} and {@link
   * KeyField}.  A good starting point is {@link Entity}.</p>
   *
   * @author Mark Hayes
   */
  public class AnnotationModel extends EntityModel {
  
      private static class EntityInfo {
          PrimaryKeyMetadata priKey;
          Map<String, SecondaryKeyMetadata> secKeys =
              new HashMap<String, SecondaryKeyMetadata>();
      }
  
      private Map<String, ClassMetadata> classMap;
      private Map<String, EntityInfo> entityMap;
      
      /*
       * This set records the special classes, i.e., enum and array type. 
       * [#19377]
       */
      private Set<String> registeredSpecialClasses;
  
      /**
       * Constructs a model for annotated entity classes.
       */
      public AnnotationModel() {
          super();
          classMap = new HashMap<String, ClassMetadata>();
          entityMap = new HashMap<String, EntityInfo>();
          registeredSpecialClasses = new HashSet<String>();
      }
  
      /* EntityModel methods */
  
      @Override
      public synchronized Set<String> getKnownClasses() {
          return Collections.unmodifiableSet
              (new HashSet<String>(classMap.keySet()));
      }
      
      @Override
      public Set<String> getKnownSpecialClasses() {
          return Collections.unmodifiableSet(registeredSpecialClasses);
      }
  
      @Override
      public synchronized EntityMetadata getEntityMetadata(String className) {
          /* Call getClassMetadata to collect metadata. */
          getClassMetadata(className);
          /* Return the collected entity metadata. */
          EntityInfo info = entityMap.get(className);
          if (info != null) {
              return new EntityMetadata
                  (className, info.priKey,
                   Collections.unmodifiableMap(info.secKeys));
          } else {
              return null;
          }
      }
  
      @Override
      public synchronized ClassMetadata getClassMetadata(String className) {
          ClassMetadata metadata = classMap.get(className);
          if (metadata == null) {
              Class<?> type;
              try {
                  type = resolveClass(className);
              } catch (ClassNotFoundException e) {
                  return null;
              }
              
              /* 
               * Adds enum or array types to registeredSpecialClasses set, and
               * does not create metadata for them. [#19377]
               */
              if (type.isEnum() ||
                  type.isArray()) {
                  registeredSpecialClasses.add(className);
              }
              
              /* Get class annotation. */
              Entity entity = type.getAnnotation(Entity.class);
              Persistent persistent = type.getAnnotation(Persistent.class);
              if (entity == null && persistent == null) {
                  return null;
              }
              if (type.isEnum() ||
                  type.isInterface() ||
                  type.isPrimitive()) {
                  throw new IllegalArgumentException
                      ("@Entity and @Persistent not allowed for enum, " +
                       "interface, or primitive type: " + type.getName());
              }
              if (entity != null && persistent != null) {
                  throw new IllegalArgumentException
                      ("Both @Entity and @Persistent are not allowed: " +
                       type.getName());
              }
              boolean isEntity;
              int version;
              String proxiedClassName;
              if (entity != null) {
                  isEntity = true;
                  version = entity.version();
                  proxiedClassName = null;
              } else {
                  isEntity = false;
                  version = persistent.version();
                  Class proxiedClass = persistent.proxyFor();
                  proxiedClassName = (proxiedClass != void.class) ?
                                      proxiedClass.getName() : null;
              }
              /* Get instance fields. */
              List<Field> fields = new ArrayList<Field>();
              boolean nonDefaultRules = getInstanceFields(fields, type);
              Collection<FieldMetadata> nonDefaultFields = null;
              if (nonDefaultRules) {
                  nonDefaultFields = new ArrayList<FieldMetadata>(fields.size());
                  for (Field field : fields) {
                      nonDefaultFields.add(new FieldMetadata
                          (field.getName(), field.getType().getName(),
                           type.getName()));
                  }
                  nonDefaultFields =
                      Collections.unmodifiableCollection(nonDefaultFields);
              }
              /* Get the rest of the metadata and save it. */
              metadata = new ClassMetadata
                  (className, version, proxiedClassName, isEntity,
                   getPrimaryKey(type, fields),
                   getSecondaryKeys(type, fields),
                   getCompositeKeyFields(type, fields),
                   nonDefaultFields);
              classMap.put(className, metadata);
              /* Add any new information about entities. */
              updateEntityInfo(metadata);
          }
          return metadata;
      }
  
      /**
       * Fills in the fields array and returns true if the default rules for
       * field persistence were overridden.
       */
      private boolean getInstanceFields(List<Field> fields, Class<?> type) {
          boolean nonDefaultRules = false;
          for (Field field : type.getDeclaredFields()) {
              boolean notPersistent =
                  (field.getAnnotation(NotPersistent.class) != null);
              boolean notTransient = 
                  (field.getAnnotation(NotTransient.class) != null);
              if (notPersistent && notTransient) {
                  throw new IllegalArgumentException
                      ("Both @NotTransient and @NotPersistent not allowed");
              }
              if (notPersistent || notTransient) {
                  nonDefaultRules = true;
              }
              int mods = field.getModifiers();
  
              if (!Modifier.isStatic(mods) &&
                  !notPersistent &&
                  (!Modifier.isTransient(mods) || notTransient)) {
                  /* Field is DPL persistent. */
                  fields.add(field);
              } else {
                  /* If non-persistent, no other annotations should be used. */
                  if (field.getAnnotation(PrimaryKey.class) != null ||
                      field.getAnnotation(SecondaryKey.class) != null ||
                      field.getAnnotation(KeyField.class) != null) {
                      throw new IllegalArgumentException
                          ("@PrimaryKey, @SecondaryKey and @KeyField not " +
                           "allowed on non-persistent field");
                  }
              }
          }
          return nonDefaultRules;
      }
  
      private PrimaryKeyMetadata getPrimaryKey(Class<?> type,
                                               List<Field> fields) {
          Field foundField = null;
          String sequence = null;
          for (Field field : fields) {
              PrimaryKey priKey = field.getAnnotation(PrimaryKey.class);
              if (priKey != null) {
  