因为一个奇怪的NullPointerException,我被困在我的项目上好几个小时

时间:2014-06-11 13:12:06

标签: drools optaplanner

运行我的问题的解算器时,我收到以下错误消息:

    Exception executing consequence for rule "addMarks" in com.abcdl.be.solver: [Error: getEndTime(): null]
    [Near : {... getEndTime() ....}] 
...

消息说规则中的getEndTime()方法" addMarks"返回null。 这是drools文件:

    // ############################################################################
// Hard constraints
// ############################################################################

rule "RespectDependencies" // Respect all the dependencies in the input file

    when
        Dependency(respected() ==  false)
    then
        scoreHolder.addHardConstraintMatch(kcontext, 0, -1);

end

rule "addMarks" //insert a Mark each time a process chain starts or ends

    when
        Node($startTime : getStartTime(), $endTime : getEndTime())

    then
        insertLogical(new Mark($startTime));
        insertLogical(new Mark($endTime));

end

rule "resourcesLimit" // At any time, The number of resources used must not exceed the total number of resources available

    when
        Mark($startTime: time)
        Mark(time > $startTime, $endTime : time)
        not Mark(time > $startTime, time < $endTime)
        $total : Number(intValue > Global.getInstance().getAvailableResources() ) from  
            accumulate(Node(getEndTime() >=$endTime, getStartTime()<= $startTime, $res : resources), sum($res))
    then
            scoreHolder.addHardConstraintMatch(kcontext, 1,  (Global.getInstance().getAvailableResources() - $total.intValue()) * ($endTime - $startTime));             
end

rule "masterDataManagement"  // Parallel loading is forbidden

    when
        $n1 : Node(md != "", $md : md, $id : id)
        $n2 : Node(id > $id, md == $md)  // We make sure to check only different nodes through the condition "id > $id"
        eval(Graph.getInstance().getPaths($n1, $n2).size() == 0)

    then
        scoreHolder.addHardConstraintMatch(kcontext, 2, -1);    
end

// ############################################################################
// Soft constraints
// ############################################################################

rule "MaximizeResources" //Maximize use of available resources at any time

    when
        Mark($startTime: time)
        Mark(time > $startTime, $endTime : time)
        not Mark(time > $startTime, time < $endTime)
        $total : Number(intValue < Global.getInstance().getAvailableResources() ) from  
            accumulate(Node(getEndTime() >=$endTime, getStartTime()<= $startTime, $res : resources), sum($res))

    then
        scoreHolder.addHardConstraintMatch(kcontext, 0, ($total.intValue() - Global.getInstance().getAvailableResources()) * ($endTime - $startTime)); 
end 



rule "MinimizeTotalTime" // Minimize the total process time
    when
        Problem($totalTime : getTotalTime())
    then
        scoreHolder.addSoftConstraintMatch(kcontext, 1, -$totalTime);
end

Node是规划实体,返回null的方法getStartTime()和getEndTime()在规划实体中定义

规划实体代码:

@PlanningEntity(difficultyComparatorClass = NodeDifficultyComparator.class)
        public class Node extends ProcessChain {

    private Node parent; // Planning variable: changes during planning, between score calculations

private int id; // Used as an identifier for each node. Different nodes cannot have the same id

public Node(String name, String type, int time, int resources, String md, int id)
{
    super(name, "", time, resources, "", type, md);
    this.delay = "";
    this.id = id;
}

public Node()
{
    super();
    this.delay = "";
}

@PlanningVariable(valueRangeProviderRefs = {"parentRange"}, nullable = false) 
public Node getParent() {
    return parent;
}

public void setParent(Node parent) {
    this.parent = parent;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String toString()
{
    if(this.type.equals("AND"))
        return delay;
    if(!this.md.isEmpty())
        return Tools.excerpt(name+" : "+this.md);

     return Tools.excerpt(name);
}

public boolean equals( Object o ) {
    if (o == this)
        return true;

    if (o instanceof Node) {
        return  
            this.name.equals(((Node)o).name);  
    } else {
        return false;
    }
}
 // ************************************************************************
// Complex methods
// ************************************************************************

 public int getStartTime()
 {
    return Graph.getInstance().getNode2times().get(this).getFirst();        
 }


public int getEndTime()
{ 
    return  Graph.getInstance().getNode2times().get(this).getSecond();   
}

 @ValueRangeProvider(id = "parentRange")
 public Collection<Node> getPossibleParents()
 {  
     Collection<Node> nodes = Graph.getInstance().getNodes();
     nodes.remove(this); // We remove this node from the list
     nodes.remove(Graph.getInstance().getParents(this)); // We remove its parents from the list
     return nodes;
 }

/**
 * The normal methods {@link #equals(Object)} and {@link #hashCode()} cannot be used because the rule engine already
 * requires them (for performance in their original state).
 * @see #solutionHashCode()
 */
public boolean solutionEquals(Object o) {
    if (this == o) {
        return true;
    } else if (o instanceof Node) {
        Node other = (Node) o;
        return new EqualsBuilder()
                .append(name, other.name)
                .isEquals();
    } else {
        return false;
    }
}

/**
 * The normal methods {@link #equals(Object)} and {@link #hashCode()} cannot be used because the rule engine already
 * requires them (for performance in their original state).
 * @see #solutionEquals(Object)
 */
public int solutionHashCode() {
    return new HashCodeBuilder()
            .append(name)
            .toHashCode();
}

这是非常奇怪的原因node2times()。get()不会为Graph类中的所有节点返回null。我做了一个测试,以确保:

public class Graph {
 private ArrayList<Node> nodes;
...

 public void test()
{
   for(Node node : nodes)
    {
        int time = 0;
         try{
             time =  getNode2times().get(node).getFirst();
             System.out.print(node+"   :  "+"Start time  = "+time);
         }
         catch(NullPointerException e)
         {
             System.out.println("StartTime is null for node : " +node);
         }
         try{
         time = node.getEndTime();
         System.out.println("    End time = "+time);
     }
     catch(NullPointerException e)
     {
         System.out.println("EndTime is null for node : " +node);
     }

    }
}

...
}

1 个答案:

答案 0 :(得分:2)

您正在超载Node.equals(),但没有Node.hashCode()

您正在使用地图:节点到时间(如果我可以信任您使用的名称)。

这违反了将对象用作HashMap中的键的合同。