Java tutorial
/* * Copyright Paolo Dragone 2014. * Copyright Alessandro Ronca 2014. * * This file is part of Wiktionary Ontology. * * Wiktionary Ontology is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Wiktionary Ontology is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Wiktionary Ontology. If not, see <http://www.gnu.org/licenses/>. */ package org.dragoneronca.nlp.wol.domain; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.log4j.Logger; import org.dragoneronca.nlp.wol.WolConfiguration; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * An iterator over entities of type T. * <p/> * It performs a bounding of the results of the queries in order to limit the memory needed to * iterte them. * * @author Paolo Dragone * @author Alessandro Ronca */ public class WolEntityIterator<T> implements Iterator<T> { private static final Logger LOG = Logger.getLogger(WolEntityIterator.class); private static final int MAX_RETRIEVED_DELTA = 1000; private final String name; private final Class<T> tClass; private boolean clear = false; private boolean logEnabled = false; private int offset = 0; private int max = 0; private LinkedList<T> results = new LinkedList<>(); private Object[] parameters; private boolean ended = false; /** * Creates a new WolEntityIterator for entities of type tClass, using the query associated with * the given name. * * @param tClass The type of the entity returned by the query * @param name The name of the query to be executed */ public WolEntityIterator(Class<T> tClass, String name) { this.tClass = tClass; this.name = name; PropertiesConfiguration properties = WolConfiguration.getInstance().getConfiguration("environment"); this.max = properties.getInt("entity_iterator.default_max"); } public WolEntityIterator(Class<T> tClass, String name, int max, boolean logEnabled) { this(tClass, name, max); this.logEnabled = logEnabled; } /** * Creates a new WolEntityIterator for entities of type tClass, using the query associated with * the given name. * * @param tClass The type of the entity returned by the query * @param name The name of the query to be executed */ public WolEntityIterator(Class<T> tClass, String name, int max) { this.tClass = tClass; this.name = name; this.max = max + MAX_RETRIEVED_DELTA; } public WolEntityIterator(Class<T> tClass, String name, int max, boolean logEnabled, boolean clear) { this(tClass, name, max); this.logEnabled = logEnabled; this.clear = clear; } /** * Sets the parameters of the query. * <p/> * If the query has mandatory parameters they must be set before the offset next or hasNext. * * @param parameters The list of parameters (positional assignment) */ public void setParameters(Object... parameters) { this.parameters = parameters; } @Override public boolean hasNext() { return !ended && (!results.isEmpty() || retrieveResults()); } @SuppressWarnings("unchecked") private boolean retrieveResults() { if (ended) { return false; } else if (!results.isEmpty()) { return true; } WolDomainContext domainContext = WolDomainContext.getInstance(); EntityManager entityManager = domainContext.getEntityManager(); if (clear) { entityManager.clear(); } TypedQuery<T> q = entityManager.createNamedQuery(name, tClass); if (parameters != null) { int i = 1; for (Object parameter : parameters) { q.setParameter(i++, parameter); } } q.setFirstResult(offset).setMaxResults(max); long startQueryTime = System.currentTimeMillis(); if (logEnabled) { LOG.info("Starting query: " + name + "\t\tType: " + tClass.getSimpleName()); } Runtime.getRuntime().gc(); List<T> resultList = q.getResultList(); if (!resultList.isEmpty()) { results.addAll(resultList); offset += results.size(); long endQueryTime = System.currentTimeMillis(); if (logEnabled) { LOG.info("Retrieved " + results.size() + " results in " + ((endQueryTime - startQueryTime) / 1000) + " sec."); } return true; } else { ended = true; return false; } } @Override public T next() { if (!hasNext()) { return null; } return results.removeFirst(); } @Override public void remove() { throw new UnsupportedOperationException(); } }