@Override
  public Object invokeMethod(String name, Object obj) {
    Object[] args = obj.getClass().isArray() ? (Object[]) obj : new Object[] {obj};

    if (isCriteriaConstructionMethod(name, args)) {

      initializeQuery();

      uniqueResult = false;

      invokeClosureNode(args[0]);

      Object result;
      if (!uniqueResult) {
        result = query.list();
      } else {
        result = query.singleResult();
      }
      query = null;
      return result;
    }

    MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args);
    if (metaMethod != null) {
      return metaMethod.invoke(this, args);
    }

    metaMethod = queryMetaClass.getMetaMethod(name, args);
    if (metaMethod != null) {
      return metaMethod.invoke(query, args);
    }

    if (args.length == 1 && args[0] instanceof Closure) {

      final PersistentProperty property = persistentEntity.getPropertyByName(name);
      if (property instanceof Association) {
        Association association = (Association) property;
        Query previousQuery = query;
        PersistentEntity previousEntity = persistentEntity;

        Query associationQuery = null;
        try {
          associationQuery = query.createQuery(property.getName());
          if (associationQuery instanceof AssociationQuery) {
            previousQuery.add((Query.Criterion) associationQuery);
          }
          query = associationQuery;
          persistentEntity = association.getAssociatedEntity();
          invokeClosureNode(args[0]);
          return query;
        } finally {

          persistentEntity = previousEntity;
          query = previousQuery;
        }
      }
    }

    throw new MissingMethodException(name, getClass(), args);
  }
 /**
  * Get hold of the GrailsDomainClassProperty represented by the targetClass' propertyName,
  * assuming targetClass corresponds to a GrailsDomainClass.
  */
 private static PersistentProperty getGrailsDomainClassProperty(
     AbstractHibernateDatastore datastore, Class<?> targetClass, String propertyName) {
   PersistentEntity grailsClass =
       datastore != null
           ? datastore.getMappingContext().getPersistentEntity(targetClass.getName())
           : null;
   if (grailsClass == null) {
     throw new IllegalArgumentException(
         "Unexpected: class is not a domain class:" + targetClass.getName());
   }
   return grailsClass.getPropertyByName(propertyName);
 }
  protected void validatePropertyName(String propertyName, String methodName) {
    if (propertyName == null) {
      throw new IllegalArgumentException(
          "Cannot use [" + methodName + "] restriction with null property name");
    }

    PersistentProperty property = persistentEntity.getPropertyByName(propertyName);
    if (property == null && persistentEntity.getIdentity().getName().equals(propertyName)) {
      property = persistentEntity.getIdentity();
    }
    if (property == null) {
      throw new IllegalArgumentException(
          "Property ["
              + propertyName
              + "] is not a valid property of class ["
              + persistentEntity
              + "]");
    }
  }