content: package at.ac.tuwien.kr.alpha.api.impl;
  
  import static org.junit.jupiter.api.Assertions.assertEquals;
  import static org.junit.jupiter.api.Assertions.assertFalse;
  import static org.junit.jupiter.api.Assertions.assertTrue;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Map;
  import java.util.Optional;
  import java.util.Set;
  
  import org.junit.jupiter.api.Test;
  
  import at.ac.tuwien.kr.alpha.api.Alpha;
  import at.ac.tuwien.kr.alpha.api.AnswerSet;
  import at.ac.tuwien.kr.alpha.api.common.fixedinterpretations.PredicateInterpretation;
  import at.ac.tuwien.kr.alpha.api.programs.Predicate;
  import at.ac.tuwien.kr.alpha.api.programs.atoms.Atom;
  import at.ac.tuwien.kr.alpha.api.programs.terms.ConstantTerm;
  import at.ac.tuwien.kr.alpha.commons.Predicates;
  import at.ac.tuwien.kr.alpha.commons.programs.atoms.Atoms;
  import at.ac.tuwien.kr.alpha.commons.programs.terms.Terms;
  import at.ac.tuwien.kr.alpha.core.externals.AspStandardLibrary;
  import at.ac.tuwien.kr.alpha.core.externals.Externals;
  
  public class FixedInterpretationLiteralsTest {
  
  	@at.ac.tuwien.kr.alpha.api.externals.Predicate
  	public static boolean isOne(int value) {
  		return value == 1;
  	}
  
  	/**
  	 * Dummy method to test external atoms with more than one output term list.
  	 * Dummy input param which is not used exists solely to avoid producing an edge
  	 * case where there is output, but no input
  	 */
  	@SuppressWarnings("unused")
  	@at.ac.tuwien.kr.alpha.api.externals.Predicate
  	public static Set<List<ConstantTerm<String>>> connection(String dummy) {
  		Set<List<ConstantTerm<String>>> retVal = new HashSet<>();
  		List<ConstantTerm<String>> l1 = new ArrayList<>();
  		List<ConstantTerm<String>> l2 = new ArrayList<>();
  		List<ConstantTerm<String>> l3 = new ArrayList<>();
  		l1.add(Terms.newConstant("Klagenfurt"));
  		l1.add(Terms.newConstant("Villach"));
  		l2.add(Terms.newConstant("Klagenfurt"));
  		l2.add(Terms.newConstant("Graz"));
  		l3.add(Terms.newConstant("Villach"));
  		l3.add(Terms.newConstant("Salzburg"));
  		retVal.add(l1);
  		retVal.add(l2);
  		retVal.add(l3);
  		return retVal;
  	}
  
  	private static final String TEST_PROG = "positive_numeric_comparison :- 2 < 3."
  			+ "negative_numeric_comparison :- not 3 < 2."
  			+ "positive_unary_external :- &isOne[1]."
  			+ "negative_unary_external :- not &isOne[2]."
  			+ "positive_external_with_output :- "
  			+ "&stdlib_datetime_parse[\"01.01.2121 21:11:12\", \"dd.MM.yyyy HH:mm:ss\"](Y, MO, D, H, MI, S), Y = 2121, MO = 1, D = 1, H = 21, MI = 11, S = 12."
  			+ "positive_external_with_output_dontfire :- "
  			+ "&stdlib_datetime_parse[\"01.01.2121 21:11:12\", \"dd.MM.yyyy HH:mm:ss\"](Y, MO, D, H, MI, S), Y = 2345, MO = 1, D = 1, H = 21, MI = 11, S = 12."
  			+ "negative_external_with_output :- Y = 2121, MO = 1, D = 1, H = 21, MI = 11, S = 12, "
  			+ "not &stdlib_datetime_parse[\"22.02.2222 21:11:12\", \"dd.MM.yyyy HH:mm:ss\"](Y, MO, D, H, MI, S)."
  			+ "negative_external_with_output_dontfire :- Y = 2222, MO = 2, D = 22, H = 21, MI = 11, S = 12,"
  			+ "not &stdlib_datetime_parse[\"22.02.2222 21:11:12\", \"dd.MM.yyyy HH:mm:ss\"](Y, MO, D, H, MI, S)."
  			+ "negative_external_multioutput :- START = \"Graz\", END = \"Salzburg\", not &connection[train_network](START, END)."
  			+ "negative_external_multioutput_dontfire :- START = \"Klagenfurt\", END = \"Villach\", not &connection[train_network](START, END)."
  			+ "positive_external_multioutput :- START = \"Klagenfurt\", END = \"Villach\", &connection[train_network](START, END)."
  			+ "positive_external_multioutput_dontfire :- START = \"Graz\", END = \"Salzburg\", &connection[train_network](START, END)."
  			+ "positive_external_binding_output(START, END) :- &connection[train_network](START, END).";
  
  	private Alpha alpha;
  	private Map<String, PredicateInterpretation> externals;
  
  	public FixedInterpretationLiteralsTest() {
  		this.alpha = new AlphaImpl();
  		this.externals = new HashMap<>();
  		this.externals.putAll(Externals.scan(AspStandardLibrary.class));
  		this.externals.putAll(Externals.scan(FixedInterpretationLiteralsTest.class));
  	}
  
  	@Test
  	public void positiveNumericComparison() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("positive_numeric_comparison", 0)));
  	}
  
  	@Test
  	public void negativeNumericComparison() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("negative_numeric_comparison", 0)));
  	}
  
  	@Test
  	public void positiveUnaryExternal() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("positive_unary_external", 0)));
  	}
  
  	@Test
  	public void negativeUnaryExternal() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("negative_unary_external", 0)));
  	}
  
  	@Test
  	public void positiveExternalWithOutput() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("positive_external_with_output", 0)));
  	}
  
  	@Test
  	public void positiveExternalWithOutputDontfire() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertFalse(answerSet.getPredicates().contains(Predicates.getPredicate("positive_external_with_output_dontfire", 0)));
  	}
  
  	@Test
  	public void negativeExternalWithOutput() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("negative_external_with_output", 0)));
  	}
  
  	@Test
  	public void negativeExternalWithOutputDontfire() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertFalse(answerSet.getPredicates().contains(Predicates.getPredicate("negative_external_with_output_dontfire", 0)));
  	}
  
  	@Test
  	public void negativeExternalMultioutput() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("negative_external_multioutput", 0)));
  	}
  
  	@Test
  	public void negativeExternalMultioutputDontfire() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertFalse(answerSet.getPredicates().contains(Predicates.getPredicate("negative_external_multioutput_dontfire", 0)));
  	}
  
  	@Test
  	public void positiveExternalMultioutput() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertTrue(answerSet.getPredicates().contains(Predicates.getPredicate("positive_external_multioutput", 0)));
  	}
  
  	@Test
  	public void positiveExternalMultioutputDontfire() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		assertFalse(answerSet.getPredicates().contains(Predicates.getPredicate("positive_external_multioutput_dontfire", 0)));
  	}
  
  	@Test
  	public void positiveExternalBindingOutput() {
  		Optional<AnswerSet> answer = this.alpha.solve(this.alpha.readProgramString(TEST_PROG, this.externals)).findFirst();
  		assertTrue(answer.isPresent());
  		AnswerSet answerSet = answer.get();
  		Predicate pred = Predicates.getPredicate("positive_external_binding_output", 2);
  		assertTrue(answerSet.getPredicates().contains(pred));
  		Set<Atom> instances = answerSet.getPredicateInstances(pred);
  		assertEquals(3, instances.size());
  		assertTrue(instances.contains(Atoms.newBasicAtom(pred, Terms.newConstant("Klagenfurt"), Terms.newConstant("Villach"))));
  		assertTrue(instances.contains(Atoms.newBasicAtom(pred, Terms.newConstant("Klagenfurt"), Terms.newConstant("Graz"))));
  		assertTrue(instances.contains(Atoms.newBasicAtom(pred, Terms.newConstant("Villach"), Terms.newConstant("Salzburg"))));
  	}
  
  }
  