/**
*
*/
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;
}
}