/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.compiler.integrationtests;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.drools.core.test.model.Cheese;
import org.drools.core.test.model.Person;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Message;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.api.runtime.rule.QueryResults;
import org.kie.api.runtime.rule.QueryResultsRow;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
public class UpdateTest {
private static final String DELETE_TEST_DRL = "update_test.drl";
private KieSession ksession;
@Before
public void setUp() {
final KieFileSystem kfs = KieServices.Factory.get().newKieFileSystem();
kfs.write(KieServices.Factory.get().getResources()
.newClassPathResource(DELETE_TEST_DRL, DeleteTest.class));
final KieBuilder kbuilder = KieServices.Factory.get().newKieBuilder(kfs);
kbuilder.buildAll();
final List<Message> res = kbuilder.getResults().getMessages(Message.Level.ERROR);
assertEquals(res.toString(), 0, res.size());
final KieBase kbase = KieServices.Factory.get()
.newKieContainer(kbuilder.getKieModule().getReleaseId())
.getKieBase();
ksession = kbase.newKieSession();
}
@After
public void tearDown() {
ksession.dispose();
}
@Test
public void updateTheOnlyFactTest() {
final Person person = new Person("George", 18);
final FactHandle factPerson = ksession.insert(person);
assertThat(ksession.getObjects()).hasSize(1);
assertThat(ksession.getObjects().iterator().next()).isInstanceOf(Person.class);
Person personToBeVerified = (Person) ksession.getObjects().iterator().next();
verifyPerson(person, personToBeVerified, 18, "George", true);
ksession.update(factPerson, new Person("Henry", 21));
verifyFactsPresentInSession(1, Person.class);
personToBeVerified = (Person) ksession.getObjects().iterator().next();
verifyPerson(person, personToBeVerified, 21, "Henry", false);
}
@Test(expected = NullPointerException.class)
public void updateWithNullTest() {
final Person person = new Person("George", 18);
final FactHandle factPerson = ksession.insert(person);
verifyFactsPresentInSession(1, Person.class);
ksession.update(factPerson, null);
}
@Test
public void updateWithDifferentClassGetQueryResultsTest() {
final Person person = new Person("George", 18);
final FactHandle fact = ksession.insert(person);
verifyFactsWithQuery(Person.class, "persons", person);
final Cheese cheese = new Cheese("Camembert", 2);
ksession.update(fact, cheese);
verifyWithQueryNoPersonsPresentInFacts();
verifyFactsPresentInSession(1, Cheese.class);
Cheese cheeseToBeVerified = (Cheese) ksession.getObjects().iterator().next();
verifyCheese(cheeseToBeVerified, 2, "Camembert");
cheeseToBeVerified = verifyFactPresentInSession(fact, Cheese.class);
verifyCheese(cheeseToBeVerified, 2, "Camembert");
}
@Test
public void updateWithDifferentClassGetObjectsTest() {
final Person person = new Person("George", 18);
final FactHandle factPerson = ksession.insert(person);
final Person personToBeVerified = verifyFactsPresentInSession(1, Person.class).get(0);
assertThat(personToBeVerified).isEqualTo(person);
final Cheese cheese = new Cheese("Camembert", 50);
ksession.update(factPerson, cheese);
verifyFactsPresentInSession(1, Cheese.class);
final Cheese cheeseToBeVerified = (Cheese) ksession.getObjects().iterator().next();
verifyCheese(cheeseToBeVerified, 50, "Camembert");
}
@Test
public void updateFireRulesTest() {
final Person george = new Person("George", 17);
final Person henry = new Person("Henry", 25);
final FactHandle georgeFact = ksession.insert(george);
ksession.insert(henry);
verifyFactsWithQuery(Person.class, "persons", george, henry);
final List<Person> drivers = new ArrayList<>();
ksession.setGlobal("drivers", drivers);
assertThat(ksession.fireAllRules()).isEqualTo(1);
verifyList(drivers, george, henry);
george.setAge(18);
ksession.update(georgeFact, george);
verifyFactsWithQuery(Person.class, "persons", george, henry);
assertThat(ksession.fireAllRules()).isEqualTo(1);
verifyList(drivers, null, george, henry);
}
@Test
public void updateFactOnRuleFireTest() {
final Cheese camembert = new Cheese("Camembert", 19);
final Cheese cheddar = new Cheese("Cheddar", 45);
ksession.insert(camembert);
ksession.insert(cheddar);
verifyFactsWithQuery(Cheese.class, "cheeseTypes", camembert, cheddar);
final List<Cheese> expensiveCheese = new ArrayList<>();
ksession.setGlobal("expensiveCheese", expensiveCheese);
final int firedRules = ksession.fireAllRules();
assertThat(firedRules).isEqualTo(2);
verifyList(expensiveCheese, camembert, cheddar);
verifyFactsWithQuery(Cheese.class, "cheeseTypes", camembert, cheddar);
assertThat(camembert.getPrice()).isEqualTo(21);
assertThat(cheddar.getPrice()).isEqualTo(45);
}
private <T> void verifyFactsWithQuery(final Class<T> expectedClassOfFacts, final String queryToGetFacts, final T... factsToVerify) {
final QueryResults results = ksession.getQueryResults(queryToGetFacts);
assertThat(results).isNotEmpty();
final QueryResultsRow resultsRow = results.iterator().next();
assertThat(resultsRow.get("$" + queryToGetFacts)).isInstanceOf(List.class);
final List<Object> objects = (List<Object>) resultsRow.get("$" + queryToGetFacts);
assertThat(objects).hasSize(factsToVerify.length);
assertThat(objects).hasOnlyElementsOfType(expectedClassOfFacts);
assertThat(objects).containsAll(Arrays.asList(factsToVerify));
}
private void verifyWithQueryNoPersonsPresentInFacts() {
QueryResults results = ksession.getQueryResults("persons");
assertThat(results).isNotEmpty();
results = ksession.getQueryResults("persons");
assertThat(results).isNotEmpty();
final QueryResultsRow resultsRow = results.iterator().next();
assertThat(resultsRow.get("$persons")).isInstanceOf(List.class);
final List<Object> persons = (List<Object>) resultsRow.get("$persons");
assertThat(persons).isEmpty();
}
private <T> List<T> verifyFactsPresentInSession(final int expectedCountOfFacts, final Class<T> expectedClassOfFacts) {
if (expectedCountOfFacts < 1) {
assertThat(ksession.getObjects()).isEmpty();
} else {
assertThat(ksession.getObjects()).hasSize(expectedCountOfFacts);
assertThat(ksession.getObjects()).hasOnlyElementsOfType(expectedClassOfFacts);
return (List<T>) new ArrayList<Object>(ksession.getObjects());
}
return null;
}
private <T> T verifyFactPresentInSession(final FactHandle factToVerify, final Class<T> expectedClassOfFact) {
assertThat(ksession.getObject(factToVerify)).isNotNull();
assertThat(ksession.getObject(factToVerify)).isInstanceOf(expectedClassOfFact);
return (T) ksession.getObject(factToVerify);
}
private void verifyCheese(final Cheese cheeseToBeVerified, final int price, final String type) {
assertThat(cheeseToBeVerified.getPrice()).isEqualTo(price);
assertThat(cheeseToBeVerified.getType()).isEqualTo(type);
}
private void verifyPerson(final Person original, final Person personToBeVerified, final int age, final String name, final boolean shouldBeEqual) {
if (original != null) {
if (shouldBeEqual) {
assertThat(personToBeVerified).isEqualTo(original);
} else {
assertThat(personToBeVerified).isNotEqualTo(original);
}
}
assertThat(personToBeVerified.getAge()).isEqualTo(age);
assertThat(personToBeVerified.getName()).isEqualTo(name);
}
private <T> void verifyList(final List<T> list, final T entryNotToContain, final T... entriesToContain) {
assertThat(list).isNotEmpty();
assertThat(list).hasSize(entriesToContain.length);
assertThat(list).containsAll(Arrays.asList(entriesToContain));
if (entryNotToContain != null) {
assertThat(list).doesNotContain(entryNotToContain);
}
}
}