/** * */ package xhail.core.terms; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import org.apache.commons.collections4.iterators.ArrayIterator; import xhail.core.Buildable; /** * @author stefano * */ public class Clause implements Iterable<Literal> { public static class Builder implements Buildable<Clause> { private Set<Literal> body = new LinkedHashSet<>(); private Atom head = null; public Builder addLiteral(Literal literal) { if (null == literal) throw new IllegalArgumentException("Illegal 'literal' argument in Clause.Builder.addLiteral(Literal): " + literal); body.add(literal); return this; } public Builder addLiterals(Collection<Literal> literals) { if (null == literals) throw new IllegalArgumentException("Illegal 'literals' argument in Clause.Builder.addLiteral(Collection<Literal>): " + literals); body.addAll(literals); return this; } @Override public Clause build() { return new Clause(this); } public Builder clearBody() { body.clear(); return this; } public Builder removeLiteral(Literal literal) { if (null == literal) throw new IllegalArgumentException("Illegal 'literal' argument in Clause.Builder.removeLiteral(Literal): " + literal); body.remove(literal); return this; } public Builder removeLiterals(Collection<Literal> literals) { if (null == literals) throw new IllegalArgumentException("Illegal 'literals' argument in Clause.Builder.removeLiteral(Collection<Literal>): " + literals); body.removeAll(literals); return this; } public Builder setHead(Atom head) { this.head = head; return this; } } private final Literal[] body; private final Atom head; private Clause(Builder builder) { if (null == builder) throw new IllegalArgumentException("Illegal 'builder' argument in Clause(Clause.Builder): " + builder); this.body = builder.body.toArray(new Literal[builder.body.size()]); this.head = builder.head; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Clause other = (Clause) obj; if (!Arrays.equals(body, other.body)) return false; if (head == null) { if (other.head != null) return false; } else if (!head.equals(other.head)) return false; return true; } public Literal[] getBody() { return body; } public Literal getBody(int index) { if (index < 1 || index > body.length) throw new IndexOutOfBoundsException("Illegal 'index' argument in Clause.getBody(int): " + index); return body[index - 1]; } public Atom getHead() { return head; } public int getSize() { return body.length; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(body); result = prime * result + ((head == null) ? 0 : head.hashCode()); return result; } @Override public Iterator<Literal> iterator() { return new ArrayIterator<>(body); } public int getLevels() { int result = 0; for (Literal literal : body) { int level = literal.getLevel(); if (level > result) result = level; } return result; } @Override public String toString() { String result = ""; if (null != head) result += head.toString(); if (body.length > 0 || null == head) { result += ":-"; for (int i = 0; i < body.length; i++) { if (i > 0) result += ","; result += body[i].toString(); } } result += "."; return result; } }