package de.uni_hildesheim.sse.trans.convert;

import java.util.Set;

import org.junit.Assert;
import org.junit.Test;

import de.uni_hildesheim.sse.model.cst.ConstraintSyntaxTree;
import de.uni_hildesheim.sse.model.cst.OCLFeatureCall;
import de.uni_hildesheim.sse.model.cst.VariablePool;
import de.uni_hildesheim.sse.model.varModel.DecisionVariableDeclaration;
import de.uni_hildesheim.sse.model.varModel.Project;
import de.uni_hildesheim.sse.model.varModel.datatypes.BooleanType;
import de.uni_hildesheim.sse.model.varModel.datatypes.OclKeyWords;

/**
 * Tests the {@link LiteralFinder}.
 * @author El-Sharkawy
 *
 */
public class LiteralFinderTest {

    /**
     * Tests whether the result of two different {@link ConstraintSyntaxTree}s with the same literals is same.
     */
    @Test
    public void testEquality() {
        Project model = new Project("TestModel");
        VariablePool pool = new VariablePool();
        
        DecisionVariableDeclaration declA = new DecisionVariableDeclaration("a", BooleanType.TYPE, model);
        DecisionVariableDeclaration declB = new DecisionVariableDeclaration("b", BooleanType.TYPE, model);
        DecisionVariableDeclaration declC = new DecisionVariableDeclaration("c", BooleanType.TYPE, model);
        
        model.add(declA);
        model.add(declB);
        model.add(declC);
        
        // cst1 = (a or b) or (not c)
        ConstraintSyntaxTree cst1 = new OCLFeatureCall(pool.obtainVariable(declA), OclKeyWords.OR,
            pool.obtainVariable(declB));
        cst1 = new OCLFeatureCall(cst1, OclKeyWords.OR,
            new OCLFeatureCall(pool.obtainVariable(declC), OclKeyWords.NOT));
        
        // cst2 = (not c or b) or (a)
        ConstraintSyntaxTree cst2 = new OCLFeatureCall(new OCLFeatureCall(pool.obtainVariable(declC), OclKeyWords.NOT),
            OclKeyWords.OR, pool.obtainVariable(declB));
        cst2 = new OCLFeatureCall(cst2, OclKeyWords.OR, pool.obtainVariable(declA));
        
        // Test: cst1 and cst2 should have the same literals
        LiteralFinder finder = new LiteralFinder(cst1);
        Set<String> firstLiterals = finder.getDeclarations();
        finder = new LiteralFinder(cst2);
        Set<String> secondLiterals = finder.getDeclarations();
        Assert.assertTrue(firstLiterals.containsAll(secondLiterals));
        Assert.assertTrue(secondLiterals.containsAll(firstLiterals));
    }
    
    /**
     * Tests whether result of positive/negative variables is correct.
     */
    @Test
    public void testCorrectOutput() {
        Project model = new Project("TestModel");
        VariablePool pool = new VariablePool();
        
        DecisionVariableDeclaration declA = new DecisionVariableDeclaration("a", BooleanType.TYPE, model);
        DecisionVariableDeclaration declB = new DecisionVariableDeclaration("b", BooleanType.TYPE, model);
        
        model.add(declA);
        model.add(declB);
        
        // cst = a or not(b)
        ConstraintSyntaxTree cst = new OCLFeatureCall(pool.obtainVariable(declA), OclKeyWords.OR,
                new OCLFeatureCall(pool.obtainVariable(declB), OclKeyWords.NOT));
        
        // Test: cst1 and cst2 should have the same literals
        LiteralFinder finder = new LiteralFinder(cst);
        Set<String> literals = finder.getDeclarations();
        Assert.assertEquals(2, literals.size());
        Assert.assertTrue(literals.contains(declA.getName()));
        Assert.assertTrue(literals.contains("not(" + declB.getName() + ")"));
    }
}
