001    package aima.logic.fol.kb.data;
002    
003    import aima.logic.fol.parsing.ast.AtomicSentence;
004    import aima.logic.fol.parsing.ast.Term;
005    
006    /**
007     * Artificial Intelligence A Modern Approach (2nd Edition): page 204.
008     * 
009     * A literal is either an atomic sentence (a positive literal) or
010     * a negated atomic sentence (a negative literal).
011     * 
012     */
013    
014    /**
015     * @author Ciaran O'Reilly
016     * 
017     */
018    public class Literal {
019            private AtomicSentence atom = null;
020            private boolean negativeLiteral = false;
021            private String strRep = null;
022            private int hashCode = 0;
023    
024            public Literal(AtomicSentence atom) {
025                    this.atom = atom;
026            }
027    
028            public Literal(AtomicSentence atom, boolean negated) {
029                    this.atom = atom;
030                    this.negativeLiteral = negated;
031            }
032    
033            public Literal newInstance(AtomicSentence atom) {
034                    return new Literal(atom, negativeLiteral);
035            }
036    
037            public boolean isPositiveLiteral() {
038                    return !negativeLiteral;
039            }
040    
041            public boolean isNegativeLiteral() {
042                    return negativeLiteral;
043            }
044    
045            public AtomicSentence getAtomicSentence() {
046                    return atom;
047            }
048    
049            public String toString() {
050                    if (null == strRep) {
051                            StringBuilder sb = new StringBuilder();
052                            if (isNegativeLiteral()) {
053                                    sb.append("~");
054                            }
055                            sb.append(getAtomicSentence().toString());
056                            strRep = sb.toString();
057                    }
058    
059                    return strRep;
060            }
061    
062            @Override
063            public boolean equals(Object o) {
064    
065                    if (this == o) {
066                            return true;
067                    }
068                    if (o.getClass() != getClass()) {
069                            // This prevents ReducedLiterals
070                            // being treated as equivalent to
071                            // normal Literals.
072                            return false;
073                    }
074                    if (!(o instanceof Literal)) {
075                            return false;
076                    }
077                    Literal l = (Literal) o;
078                    return l.isPositiveLiteral() == isPositiveLiteral()
079                                    && l.getAtomicSentence().getSymbolicName().equals(
080                                                    atom.getSymbolicName())
081                                    && l.getAtomicSentence().getArgs().equals(atom.getArgs());
082            }
083    
084            @Override
085            public int hashCode() {
086                    if (0 == hashCode) {
087                            hashCode = 17;
088                            hashCode = 37 * hashCode + (getClass().getSimpleName().hashCode())
089                                            + (isPositiveLiteral() ? "+".hashCode() : "-".hashCode())
090                                            + atom.getSymbolicName().hashCode();
091                            for (Term t : atom.getArgs()) {
092                                    hashCode = 37 * hashCode + t.hashCode();
093                            }
094                    }
095                    return hashCode;
096            }
097    }