package test;
import org.apache.lucene.search.Query;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hibernate.search.query.engine.spi.EntityInfo;
import org.hibernate.search.query.engine.spi.HSQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pt.ist.fenixframework.Atomic;
import pt.ist.fenixframework.DomainRoot;
import pt.ist.fenixframework.FenixFramework;
import pt.ist.fenixframework.hibernatesearch.HibernateSearchSupport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class MainApp {
private static final Logger logger = LoggerFactory.getLogger(MainApp.class);
public static final int AUTH_COUNT = 10;
public static final int PUB_COUNT = 20;
public static final int BOOK_COUNT = 50;
public static final int SLEEP_TIME = 10000;
public static final String NAME_SPLITTER = "_";
private static String nodeName;
public static void main(String[] args) {
if (args.length < 2) {
error("Expected two arguments: <hostname> and <number of nodes expected>");
System.exit(1);
}
nodeName = args[0];
int expectedNodes = Integer.parseInt(args[1]);
try {
initDomain();
sleepAWhile();
doQueries();
modifyDomain();
sleepAWhile();
doMoreQueries();
FenixFramework.barrier("finish", expectedNodes);
} catch (InterruptedException e) {
logger.error("Interrupted!");
} catch (Exception e) {
logger.error("Error", e);
} finally {
FenixFramework.shutdown();
}
}
@Atomic
public static void populateAuthors() {
DomainRoot domainRoot = FenixFramework.getDomainRoot();
// Authors
debug("Populate " + AUTH_COUNT + " authors");
for (int i = 0; i < AUTH_COUNT; i++) {
domainRoot.addTheAuthors(new Author(authorName(i)));
}
}
@Atomic
public static void populatedPublishers() {
DomainRoot domainRoot = FenixFramework.getDomainRoot();
// Publishers
debug("Populate " + PUB_COUNT + " publishers");
for (int i = 0; i < PUB_COUNT; i++) {
domainRoot.addThePublishers(new Publisher(publisherName(i)));
}
}
@Atomic
public static void populateBooks() {
DomainRoot domainRoot = FenixFramework.getDomainRoot();
// Books
debug("Populate " + BOOK_COUNT + " books");
for (int i = 0; i < BOOK_COUNT; i++) {
Book book = null;
switch (i%3) {
case 0:
book = new Book(bookName(i));
break;
case 1:
book = new ComicBook(bookName(i));
break;
case 2:
book = new ScifiBook(bookName(i));
break;
}
domainRoot.addTheBooks(book);
}
}
public static void initDomain() {
info("Populate domain");
populateAuthors();
populatedPublishers();
populateBooks();
info("Populate domain finished");
}
@Atomic
public static void doQueries() {
debug("Doing example queries. Configured " + AUTH_COUNT + " authors, " + PUB_COUNT
+ " publishers, and " + BOOK_COUNT + " books");
debug("Find " + bookName(BOOK_COUNT / 2) + ": " + performQuery(Book.class, "bookName", bookName(BOOK_COUNT / 2)));
debug("Find Book*1: " + performWildcardQuery(Book.class, "bookName", "book*1"));
debug("Find ScifiBook*: " + performWildcardQuery(ScifiBook.class, "bookName", "book*"));
debug("Find Scifi Books by " + authorName(0) + ": " + performQuery(ScifiBook.class, "authors.id",
getAuthorByName(authorName(0)).getExternalId()));
}
@Atomic
public static void modifyDomain() {
debug("Adding books to " + authorName(0));
Author auth0 = getAuthorByName(authorName(0));
for (int i = 0; i < 20; i++) {
auth0.addBooks(getBookByName(bookName(i)));
}
}
@Atomic
public static void doMoreQueries() {
debug("Find Scifi Books by " + authorName(0) + ": " + performQuery(ScifiBook.class, "authors.id",
getAuthorByName(authorName(0)).getExternalId()));
}
// See
// https://docs.jboss.org/hibernate/search/4.2/reference/en-US/html_single/#section-building-lucene-queries
// for more examples on how to build queries
@SuppressWarnings("unchecked")
public static <T> Collection<T> performQuery(Class<T> cls, String field, String queryString) {
ArrayList<T> matchingObjects = new ArrayList<T>();
QueryBuilder qb = HibernateSearchSupport.getSearchFactory().buildQueryBuilder().forEntity(cls).get();
Query query = qb.keyword().onField(field).matching(queryString).createQuery();
HSQuery hsQuery = HibernateSearchSupport.getSearchFactory().createHSQuery().luceneQuery(query)
.targetedEntities(Arrays.<Class<?>>asList(cls));
hsQuery.getTimeoutManager().start();
for (EntityInfo ei : hsQuery.queryEntityInfos()) {
matchingObjects.add((T) FenixFramework.getDomainObject((String) ei.getId()));
}
hsQuery.getTimeoutManager().stop();
return matchingObjects;
}
@SuppressWarnings("unchecked")
public static <T> Collection<T> performWildcardQuery(Class<T> cls, String field, String queryString) {
ArrayList<T> matchingObjects = new ArrayList<T>();
QueryBuilder qb = HibernateSearchSupport.getSearchFactory().buildQueryBuilder().forEntity(cls).get();
Query query = qb.keyword().wildcard().onField(field).matching(queryString).createQuery();
HSQuery hsQuery = HibernateSearchSupport.getSearchFactory().createHSQuery().luceneQuery(query)
.targetedEntities(Arrays.<Class<?>>asList(cls));
hsQuery.getTimeoutManager().start();
for (EntityInfo ei : hsQuery.queryEntityInfos()) {
matchingObjects.add((T) FenixFramework.getDomainObject((String) ei.getId()));
}
hsQuery.getTimeoutManager().stop();
return matchingObjects;
}
@Atomic
public static Author getAuthorByName(String authorName) {
DomainRoot domainRoot = FenixFramework.getDomainRoot();
for (Author author : domainRoot.getTheAuthors()) {
if (author.getName().equals(authorName)) {
return author;
}
}
return null;
}
@Atomic
public static Book getBookByName(String bookName) {
DomainRoot domainRoot = FenixFramework.getDomainRoot();
for (Book book : domainRoot.getTheBooks()) {
if (book.getBookName().equals(bookName)) {
return book;
}
}
return null;
}
public static void sleepAWhile() {
try {
debug("Sleeping for " + SLEEP_TIME + " milliseconds");
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
//no-op
}
}
private static String authorName(int id) {
return "Author" + NAME_SPLITTER + nodeName + NAME_SPLITTER + id;
}
private static String bookName(int id) {
return "Book" + NAME_SPLITTER + nodeName + NAME_SPLITTER + id;
}
private static String publisherName(int id) {
return "Publisher" + NAME_SPLITTER + nodeName + NAME_SPLITTER + id;
}
private static void debug(String message) {
logger.debug("[" + nodeName + "] " + message);
}
private static void info(String message) {
logger.info("[" + nodeName + "] " + message);
}
private static void error(String message) {
logger.error("[" + nodeName + "] " + message);
}
}