package de.uni_hildesheim.sse.trans.in;

import java.io.File;
import java.io.IOException;

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.Variable;
import de.uni_hildesheim.sse.model.varModel.Project;
import de.uni_hildesheim.sse.model.varModel.datatypes.OclKeyWords;
import de.uni_hildesheim.sse.model.varModel.filter.ConstraintFinder;
import de.uni_hildesheim.sse.model.varModel.filter.DeclarationFinder;
import de.uni_hildesheim.sse.model.varModel.filter.DeclarationFinder.VisibilityType;
import de.uni_hildesheim.sse.model.varModel.filter.FilterType;
import de.uni_hildesheim.sse.trans.AllTests;
import de.uni_hildesheim.sse.trans.convert.OptimizationParameter;

/**
 * Tests for {@link ModelReader}.
 * @author El-Sharkawy
 *
 */
public class ModelReaderTest {

    /**
     * Tests the read method of the {@link ModelReader}.
     * @throws IOException when the {@link ModelReader} throws an {@link IOException}.
     */
    @Test
    public void testRead() throws IOException {
        File modelFile = new File(AllTests.INPUT_FOLDER, "testModel.model");
        ModelReader reader = new ModelReader(modelFile, new OptimizationParameter(true));
        Project project = reader.read();
        
        ConstraintFinder cFinder = new ConstraintFinder(project);
        Assert.assertEquals(7, cFinder.getConstraints().size());
        
        DeclarationFinder varFinder = new DeclarationFinder(project, FilterType.ALL, null);
        Assert.assertEquals(6, varFinder.getVariableDeclarations(VisibilityType.ALL).size());
    }
    
    /**
     * Tests the parseLine method.
     * @throws IOException when the {@link ModelReader} throws an {@link IOException}.
     */
    @Test
    public void testParseLine() throws IOException {
        File modelFile = new File(AllTests.INPUT_FOLDER, "testModel.model");
        ModelReader reader = new ModelReader(modelFile, new OptimizationParameter(true));
        
        ConstraintSyntaxTree tree = reader.parseLine("(!def(3C515_MODULE)|def(MODULES))", 0);
        Assert.assertTrue(tree instanceof OCLFeatureCall);
        OCLFeatureCall call = (OCLFeatureCall) tree;
        Assert.assertEquals(OclKeyWords.OR, call.getOperation());
        ConstraintSyntaxTree side1 = call.getParameter(0);
        ConstraintSyntaxTree side2 = call.getOperand();
        if (side1 instanceof Variable) {
            Assert.assertTrue(side2 instanceof OCLFeatureCall);
            Assert.assertEquals(OclKeyWords.NOT, ((OCLFeatureCall) side2).getOperation());
        } else if (side2 instanceof Variable) {
            Assert.assertTrue(side1 instanceof OCLFeatureCall);
            Assert.assertEquals(OclKeyWords.NOT, ((OCLFeatureCall) side1).getOperation());
        } else {
            Assert.fail("Neither side is a variable.");
        }
        
        tree = reader.parseLine(
                "((def(TR)&def(PCI)&def(NETDEVICES))|(def(NETDEVICES)&((def(TR)&def(PCI))|"
                + "(def(PCI)&(def(TR)|def(TR_MODULE)))))|def(MODULES)|!def(3C359))", 0);
        Assert.assertTrue(tree instanceof OCLFeatureCall);
    }

}
