Не удается получить доступ к элементу first () из пустого списка при использовании Grails SortedSet - PullRequest
3 голосов
/ 27 сентября 2010

Я работаю над созданием некоторых доменных объектов grails динамически, а затем добавляю им SortedSet, объявленный в другом объекте домена grails. Я создал класс Project, заполнил его значения и проверил, чтобы он действовал. Он действителен, поэтому я хочу добавить этот проект сотруднику.

Мой код, по сути, выглядит так

Employee employee = Employee.get(session.empid)
...
//populate some Project objects
...
//add projects to employee
employee.addToProjects(project)

Что здесь может пойти не так? Если я выполняю project.validate (), а затем проверяю на наличие ошибок, единственный говорит, что с проектом не связан действительный сотрудник, но это должно исчезнуть, как только я выполню employee.addToProjects. Сотрудник имеет много объектов проекта, и он объявлен так:

class Employee implements Comparable
{
    static hasMany = [projects:Project]

    static constraints = 
    {
    }

    static mapping = {
        projects cascade:"all,delete-orphan", lazy:false
    }

    SortedSet<Project> projects = new TreeSet<Project>();
}


public class Project implements Comparable
{  
    static belongsTo = [employee:Employee]

    static hasMany = [roles:Role]

    static mapping = {
          roles lazy:false, cascade:"all,delete-orphan"
    }

    @XmlElement
    List<Role> roles = new ArrayList<Role>();


    /*
     * return sorted list.  overwriting default getter was causing error upon saving multiple roles.
     *
     */
    def List getSortedRoles(){
        Collections.sort(roles, new RoleComparator());
        return roles;
    }


    String toString()
    {
        return name
    }


    // compare by latest date of roles, then by name + id
    //if this is too intrusive, implement comparator with this logic and sort on rendering page
       int compareTo(obj) {
           if(obj == null){
               return 1;
           }

           def myMaxRole = findMaxRole(roles);
           def rhsMaxRole = findMaxRole(obj.roles);

           def rcomparator = new RoleComparator();

           System.out.println(myMaxRole.title + " " + rhsMaxRole.title + " " + rcomparator.compare(myMaxRole, rhsMaxRole));
           return rcomparator.compare(myMaxRole, rhsMaxRole);
       }

    def List getExpandableRoleList()
    {
        return LazyList.decorate(roles, FactoryUtils.instantiateFactory(Role.class));
    }


    def setExpandableRoleList(List l)
    {
        return roles = l;
    }

        def Role findMaxRole(roles){
            RoleComparator rc = new RoleComparator();

            Role maxRole = roles.first();
            for(role in roles){
                if(rc.compare(maxRole, role) > 0){
                    maxRole = role;
                }
            }

            return maxRole;
        }

public class Role implements Comparable
{

    static belongsTo = [project:Project]
    static hasMany = [roleSkills:RoleSkill,roleTools:RoleTool]

    static mapping = {
        duties type:"text"
        roleSkills cascade:"all,delete-orphan", lazy:false
        roleTools cascade:"all,delete-orphan", lazy:false

    }

    static contraints = {
        endDate(nullable: true)
    }

    boolean _deleted
    static transients = ['_deleted']

    @XmlElement
    String title = ""
    @XmlElement
    String duties = ""
    @XmlElement
    int levelOfEffort
    @XmlElement
    Date startDate = new Date()
    @XmlElement
    Date endDate = new Date()
    @XmlElement
    Date lastModified = new Date()
    @XmlElement
    LocationType locationType = new LocationType(type: "Unknown")
    @XmlElement
    String rank
    @XmlElement
    List<RoleSkill> roleSkills = new ArrayList<RoleSkill>()
    @XmlElement
    List<RoleTool> roleTools  = new ArrayList<RoleTool>()

    String toString()
    {   
        return title;
    }

    int compareTo(obj) {

        return title.compareTo(obj.title)
    }

    def skills() {
        return roleSkills.collect{it.skill}
    }
    def tools() {
        return roleTools.collect{it.tool}
    }
}

Ответы [ 3 ]

13 голосов
/ 10 ноября 2010

Наличие [] .first () создает исключение «java.util.NoSuchElementException: невозможно получить доступ к элементу first ()» из пустого списка. На мой взгляд, это выглядит как «un-groovy».

Я использую сейф groovyоператор -deference (?), чтобы избежать NPE / NoSuchElementException

def list=[]
println list[0] //returns null
println list.first()    //NoSuchElementException
println list?.first()  //NoSuchElementException.  Would prefer it to return null.
def list2=[null,3,6]
println list2.first()  // returns null
println list2[0]       //returns null

Кажется разочаровывающим, что .first () - единственный метод с классным списком, который генерирует исключение.Кто-нибудь еще испытывал это?

Документация должна быть изменена, чтобы уточнить это.list [0] - возвращает ноль, если элемент не найден.не различает пустой список и случай, когда первый элемент оказывается пустым.

.first () возвращает первый элемент, только если есть первый элемент, в противном случае выдает исключение NoSuchElementException

0 голосов
/ 28 сентября 2010

вернулся к основам и написал интеграционный тест, используя ваши объекты, и все работает нормально, ваша ошибка должна быть в том, как вы сохраняете объекты

тестовый фрагмент

void testSomething() {
    def emp = new Employee(first:"Aaron", last:"Saunders")
    emp.save()

    emp =  Employee.get(1)

    emp.addToProjects(new Project(name:"Project 3"))
    emp.addToProjects(new Project(name:"Project 1"))
    emp.addToProjects(new Project(name:"Project 2"))

    emp.save()

    println Employee.get(1)

    println Employee.get(1).projects.first()
}

myобъекты ..

public class Project implements Comparable
{  
    static belongsTo = [employee:Employee]

    String name;

    static mapping = {
          roles lazy:false, cascade:"all,delete-orphan"
    }


    String toString()
    {
        return name
    }


    // compare by latest date of roles, then by name + id
    //if this is too intrusive, implement comparator with this logic and sort on rendering page
       int compareTo(obj) {
           if(obj == null){
               return 1;
           }


           return this.name.compareTo(obj.name);
       }

}

class Employee implements Comparable
{
    static hasMany = [projects:Project]

    String first, last
    static constraints = 
    {
    }

    static mapping = {
        projects cascade:"all,delete-orphan", lazy:false
    }

    SortedSet<Project> projects = new TreeSet<Project>();

    int compareTo(obj) {
        if(obj == null){
            return 1;
        }
           return this.name.compareTo(obj.name);
    }

}
0 голосов
/ 28 сентября 2010

first () является частью groovy. первый вызов пустого набора вызовет исключение для такого элемента.

добавьте проект к сотруднику и попробуйте сохранить сотрудника.

попробуйте сохранить код, например:

if(!employee.save()) 
    employee.errors.allErrors.each {
        println it
    }

попробуйте удалить строку: SortedSet projects = new TreeSet ();

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...