package org.archstudio.prolog.term; import static com.google.common.base.Preconditions.checkArgument; import java.util.Arrays; import java.util.List; import java.util.Map; import org.archstudio.prolog.engine.ProofContext; import com.google.common.collect.Lists; public class ListTerm extends AbstractTerm implements Term { private final Term head; private final Term tail; public ListTerm(Term head, Term tail) { this.head = head; // nullable this.tail = tail; // nullable } public ListTerm() { this((Term) null, (Term) null); } public ListTerm(String functor, List<Term> terms) { this(terms.get(0), terms.get(1)); checkArgument(terms.size() == 2); } public boolean isEmpty() { return head == null && tail == null; } @Override public Term resolve(ProofContext proofContext, Map<VariableTerm, Term> variables) { Term h = head == null ? null : head.resolve(proofContext, variables); Term t = tail == null ? null : tail.resolve(proofContext, variables); return new ListTerm(h, t); } protected String toStringHelper() { if (isEmpty()) { return "]"; } if (tail instanceof ListTerm) { return ", " + head + ((ListTerm) tail).toStringHelper(); } return ", " + head + ", " + tail + "]"; } @Override public String toString() { if (isEmpty()) { return "[]"; } if (tail instanceof ListTerm) { return "[" + head + ((ListTerm) tail).toStringHelper(); } return "[" + head + ", " + tail + "]"; } public int length() { if (isEmpty()) { return 0; } if (tail instanceof ListTerm) { return ((ListTerm) tail).length() + 1; } throw new UnsupportedOperationException("Cannot calculate length!"); } public List<Term> asList() { List<Term> list = Lists.newArrayList(); ListTerm lt = this; while (!lt.isEmpty()) { list.add(lt.getHead()); if (!(lt.getTail() instanceof ListTerm)) { throw new UnsupportedOperationException("Cannot create list!"); } lt = (ListTerm) lt.getTail(); } return list; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (head == null ? 0 : head.hashCode()); result = prime * result + (tail == null ? 0 : tail.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } ListTerm other = (ListTerm) obj; if (head == null) { if (other.head != null) { return false; } } else if (!head.equals(other.head)) { return false; } if (tail == null) { if (other.tail != null) { return false; } } else if (!tail.equals(other.tail)) { return false; } return true; } public Term getHead() { return head; } public Term getTail() { return tail; } public static ListTerm asListTerm(Term... terms) { return asListTerm(Arrays.asList(terms)); } public static ListTerm asListTerm(Iterable<? extends Term> terms) { return asListTerm(Lists.newArrayList(terms)); } public static ListTerm asListTerm(List<? extends Term> terms) { ListTerm lt = new ListTerm(); for (Term term : Lists.reverse(terms)) { lt = new ListTerm(term, lt); } return lt; } }