public static List<String> getDatasourceNames(PersistentEntity domainClass) {
   final Entity mappedForm = domainClass.getMapping().getMappedForm();
   if (mappedForm instanceof Mapping) {
     Mapping mapping = (Mapping) mappedForm;
     return mapping.getDatasources();
   }
   return Collections.singletonList(Mapping.DEFAULT_DATA_SOURCE);
 }
  /** Overrides the default behaviour to including binding of Grails domain classes. */
  @Override
  protected void secondPassCompile() throws MappingException {
    final Thread currentThread = Thread.currentThread();
    final ClassLoader originalContextLoader = currentThread.getContextClassLoader();
    if (!configLocked) {
      if (LOG.isDebugEnabled())
        LOG.debug(
            "[GrailsAnnotationConfiguration] ["
                + domainClasses.size()
                + "] Grails domain classes to bind to persistence runtime");

      // do Grails class configuration
      configureDomainBinder(binder, grailsApplication, domainClasses);

      for (GrailsDomainClass domainClass : domainClasses) {

        final String fullClassName = domainClass.getFullName();

        String hibernateConfig = fullClassName.replace('.', '/') + ".hbm.xml";
        final ClassLoader loader = originalContextLoader;
        // don't configure Hibernate mapped classes
        if (loader.getResource(hibernateConfig) != null) continue;

        final Mappings mappings = super.createMappings();
        if (!GrailsHibernateUtil.usesDatasource(domainClass, dataSourceName)) {
          continue;
        }

        LOG.debug(
            "[GrailsAnnotationConfiguration] Binding persistent class [" + fullClassName + "]");

        Mapping m = binder.getMapping(domainClass);
        mappings.setAutoImport(m == null || m.getAutoImport());
        binder.bindClass(domainClass, mappings, sessionFactoryBeanName);
      }
    }

    try {
      currentThread.setContextClassLoader(grailsApplication.getClassLoader());
      super.secondPassCompile();
      createSubclassForeignKeys();
    } finally {
      currentThread.setContextClassLoader(originalContextLoader);
    }

    configLocked = true;
  }
  /**
   * Populates criteria arguments for the given target class and arguments map
   *
   * @param datastore the GrailsApplication instance
   * @param targetClass The target class
   * @param c The criteria instance
   * @param argMap The arguments map
   */
  @SuppressWarnings("rawtypes")
  public static void populateArgumentsForCriteria(
      AbstractHibernateDatastore datastore,
      Class<?> targetClass,
      Criteria c,
      Map argMap,
      ConversionService conversionService,
      boolean useDefaultMapping) {
    Integer maxParam = null;
    Integer offsetParam = null;
    if (argMap.containsKey(ARGUMENT_MAX)) {
      maxParam = conversionService.convert(argMap.get(ARGUMENT_MAX), Integer.class);
    }
    if (argMap.containsKey(ARGUMENT_OFFSET)) {
      offsetParam = conversionService.convert(argMap.get(ARGUMENT_OFFSET), Integer.class);
    }
    if (argMap.containsKey(ARGUMENT_FETCH_SIZE)) {
      c.setFetchSize(conversionService.convert(argMap.get(ARGUMENT_FETCH_SIZE), Integer.class));
    }
    if (argMap.containsKey(ARGUMENT_TIMEOUT)) {
      c.setTimeout(conversionService.convert(argMap.get(ARGUMENT_TIMEOUT), Integer.class));
    }
    if (argMap.containsKey(ARGUMENT_FLUSH_MODE)) {
      c.setFlushMode(convertFlushMode(argMap.get(ARGUMENT_FLUSH_MODE)));
    }
    if (argMap.containsKey(ARGUMENT_READ_ONLY)) {
      c.setReadOnly(ClassUtils.getBooleanFromMap(ARGUMENT_READ_ONLY, argMap));
    }
    String orderParam = (String) argMap.get(ARGUMENT_ORDER);
    Object fetchObj = argMap.get(ARGUMENT_FETCH);
    if (fetchObj instanceof Map) {
      Map fetch = (Map) fetchObj;
      for (Object o : fetch.keySet()) {
        String associationName = (String) o;
        c.setFetchMode(associationName, getFetchMode(fetch.get(associationName)));
      }
    }

    final int max = maxParam == null ? -1 : maxParam;
    final int offset = offsetParam == null ? -1 : offsetParam;
    if (max > -1) {
      c.setMaxResults(max);
    }
    if (offset > -1) {
      c.setFirstResult(offset);
    }
    if (ClassUtils.getBooleanFromMap(ARGUMENT_LOCK, argMap)) {
      c.setLockMode(LockMode.PESSIMISTIC_WRITE);
      c.setCacheable(false);
    } else {
      if (argMap.containsKey(ARGUMENT_CACHE)) {
        c.setCacheable(ClassUtils.getBooleanFromMap(ARGUMENT_CACHE, argMap));
      } else {
        cacheCriteriaByMapping(targetClass, c);
      }
    }

    final Object sortObj = argMap.get(ARGUMENT_SORT);
    if (sortObj != null) {
      boolean ignoreCase = true;
      Object caseArg = argMap.get(ARGUMENT_IGNORE_CASE);
      if (caseArg instanceof Boolean) {
        ignoreCase = (Boolean) caseArg;
      }
      if (sortObj instanceof Map) {
        Map sortMap = (Map) sortObj;
        for (Object sort : sortMap.keySet()) {
          final String order =
              ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? ORDER_DESC : ORDER_ASC;
          addOrderPossiblyNested(datastore, c, targetClass, (String) sort, order, ignoreCase);
        }
      } else {
        final String sort = (String) sortObj;
        final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC;
        addOrderPossiblyNested(datastore, c, targetClass, sort, order, ignoreCase);
      }
    } else if (useDefaultMapping) {
      Mapping m = getDomainBinder().getMapping(targetClass);
      if (m != null) {
        Map sortMap = m.getSort().getNamesAndDirections();
        for (Object sort : sortMap.keySet()) {
          final String order =
              ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? ORDER_DESC : ORDER_ASC;
          addOrderPossiblyNested(datastore, c, targetClass, (String) sort, order, true);
        }
      }
    }
  }
 /**
  * Configures the criteria instance to cache based on the configured mapping.
  *
  * @param targetClass The target class
  * @param criteria The criteria
  */
 public static void cacheCriteriaByMapping(Class<?> targetClass, Criteria criteria) {
   Mapping m = getDomainBinder().getMapping(targetClass);
   if (m != null && m.getCache() != null && m.getCache().getEnabled()) {
     criteria.setCacheable(true);
   }
 }