/** * Este arquivo é parte do Biblivre3. * * Biblivre3 é um software livre; você pode redistribuí-lo e/ou * modificá-lo dentro dos termos da Licença Pública Geral GNU como * publicada pela Fundação do Software Livre (FSF); na versão 3 da * Licença, ou (caso queira) qualquer versão posterior. * * Este programa é distribuído na esperança de que possa ser útil, * mas SEM NENHUMA GARANTIA; nem mesmo a garantia implícita de * MERCANTIBILIDADE OU ADEQUAÇÃO PARA UM FIM PARTICULAR. Veja a * Licença Pública Geral GNU para maiores detalhes. * * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto * com este programa, Se não, veja em <http://www.gnu.org/licenses/>. * * @author Alberto Wagner <alberto@biblivre.org.br> * @author Danniel Willian <danniel@biblivre.org.br> * */ package biblivre3.cataloging.bibliographic; import biblivre3.circulation.lending.LendingBO; import biblivre3.config.Config; import biblivre3.config.ConfigurationEnum; import biblivre3.enums.AttributeType; import java.util.ArrayList; import biblivre3.marcutils.Indexer; import biblivre3.marcutils.MarcUtils; import org.marc4j_2_3_1.marc.Record; import java.util.Collection; import mercury.BaseBO; import biblivre3.enums.Database; import biblivre3.enums.MaterialType; import biblivre3.cataloging.holding.HoldingBO; import biblivre3.cataloging.holding.HoldingDAO; import biblivre3.circulation.reservation.ReservationBO; import biblivre3.utils.TextUtils; import java.util.List; public class BiblioSearchBO extends BaseBO { private int recordsPPage; public BiblioSearchBO() { try { final String rpp = Config.getConfigProperty(ConfigurationEnum.RECORDS_PER_PAGE); this.recordsPPage = Integer.valueOf(rpp); } catch (Exception e) { log.error(e.getMessage(), e); this.recordsPPage = 25; } } public BiblioSearchResultsDTO search(String base, String itemType, String[] searchTerms, String[] searchAttr, String[] boolOp, final int offset) { BiblioSearchResultsDTO bdto = null; final BiblioDAO dao = new BiblioDAO(); boolean searchingAssetHolding = false; boolean searchingHoldingSerial = false; String assetHolding = null; String holdingSerial = null; for (int k = 0; k < searchAttr.length; k++) { if (searchAttr[k].equals("HOLDING")) { searchingAssetHolding = true; assetHolding = searchTerms[k]; } else if (searchAttr[k].equals("BAR_CODE")) { searchingHoldingSerial = true; holdingSerial = searchTerms[k]; } } final Database database = Database.valueOf(base); Collection<RecordDTO> records; int total; if (searchingAssetHolding) { records = new ArrayList<RecordDTO>(); RecordDTO record = dao.searchByAssetHolding(assetHolding, database); if (record != null) { records.add(record); } total = records.size(); } else if (searchingHoldingSerial) { records = new ArrayList<RecordDTO>(); try { RecordDTO record = dao.searchByHoldingSerial(Integer.parseInt(holdingSerial), database); if (record != null) { records.add(record); } } catch (NumberFormatException e) { // dont find anything } total = records.size(); } else { searchTerms[0] = searchTerms[0].trim(); Object[] tuple = this.createWhereClause(searchTerms, searchAttr, boolOp); if (tuple == null) { return null; } final String clause = (String) tuple[0]; final List<String> values = (ArrayList<String>) tuple[1]; if (clause.isEmpty()) { return null; } final MaterialType materialType = MaterialType.getByCode(itemType); records = dao.search(database, materialType, clause, values, offset, recordsPPage, false); total = dao.count(database, materialType, clause, values); } return this.populateBiblioDTO(records, total, offset); } public BiblioSearchResultsDTO list(String base, String itemType, int offset) { final BiblioDAO dao = new BiblioDAO(); final Database database = Database.valueOf(base); final MaterialType materialType = MaterialType.getByCode(itemType); final Collection<RecordDTO> records = dao.list(database, materialType, offset, recordsPPage, false); int total = dao.countAll(database, materialType); return this.populateBiblioDTO(records, total, offset); } private BiblioSearchResultsDTO populateBiblioDTO(Collection<RecordDTO> records, int total, int offset) { if (records != null && !records.isEmpty()) { BiblioSearchResultsDTO bdto = new BiblioSearchResultsDTO(); HoldingBO hbo = new HoldingBO(); LendingBO lbo = new LendingBO(); ReservationBO rbo = new ReservationBO(); final ArrayList<ResultRow> al = new ArrayList<ResultRow>(); for (RecordDTO dto : records) { Record record = MarcUtils.iso2709ToRecord(dto.getIso2709()); ResultRow rr = new ResultRow(); final int recordSerial = dto.getRecordSerial(); rr.setRecordSerial(recordSerial); rr.setTitle(Indexer.listOneTitle(record)); rr.setAuthor(Indexer.listAuthors(record)); rr.setDate(Indexer.listYearOfPublication(record)); rr.setIsbn(Indexer.listIsbn(record)); rr.setLocation(Indexer.listLocation(record)); rr.setCreated(dto.getCreated()); rr.setModified(dto.getModified()); //quant - Recebe a quantidade total de exemplares de uma obra(disponíveis + indisponíveis) int quant = new HoldingDAO().countHoldings(rr.getRecordSerial()); rr.setNrholdings(quant); int totalHoldings = hbo.countHoldings(recordSerial); int availableHoldings = hbo.countAvailableHoldings(recordSerial); int lentCount = 0; int reservedCount = 0; if (availableHoldings > 0) { lentCount = lbo.countLentHoldings(recordSerial); reservedCount = rbo.countReservedHoldings(recordSerial); } rr.setHoldingsCount(totalHoldings); rr.setHoldingsAvailable(availableHoldings - lentCount); rr.setHoldingsLent(lentCount); rr.setHoldingsReserved(reservedCount); al.add(rr); } bdto.al = al; int pageCount = total / recordsPPage; bdto.totalPages = (total % recordsPPage == 0) ? pageCount : pageCount + 1; bdto.currentPage = (offset / recordsPPage) + 1; bdto.recordsPerPage = recordsPPage; bdto.totalRecords = total; return bdto; } else { return null; } } //-------------------------------------------------------------------------- /** * Creates a where clause for a prepared statement of biblio search and the corresponding values. * @param searchTerms Array of Strings with the search terms. * @param searchAttr Array of Strings with the corresponding search attributes. * @param boolOp Array of boolean operators corresponding to the search terms and attributes. * @return An array of two objects: a string with concatenated clauses and boolean operators * and an ArrayList of Strings with the values. */ public Object[] createWhereClause(final String[] searchTerms, final String[] searchAttr, final String[] boolOp) { if (searchAttr == null || searchTerms == null) { return null; } final BiblioDAO dao = new BiblioDAO(); ArrayList<String> clauses = new ArrayList<String>(); final Object[] result = new Object[2]; ArrayList<String> values = new ArrayList<String>(); ArrayList<String> newBoolOp = new ArrayList<String>(); for (int i = 0; i < searchAttr.length; i++) { final AttributeType type = AttributeType.getAttributeTypeByCode(searchAttr[i]); final String terms = TextUtils.removeDiacriticals(searchTerms[i]).toLowerCase(); if (terms == null || terms.isEmpty()) { continue; } String s[] = terms.split("\\s+"); ArrayList<String> validTerms = new ArrayList<String>(s.length); for (int j = 0; j < s.length; j++) { if (s[j] != null && (s[j].length() > 1 || TextUtils.isInteger(s[j]))) { validTerms.add(s[j]); if (j > 0) { newBoolOp.add("AND"); } } } if (validTerms.size() > 0 && i < searchAttr.length - 1) { newBoolOp.add(boolOp[i]); } for (String term : validTerms) { switch (type) { case ANY: { clauses.add(dao.createIndexClause("idx_any")); values.add(term); break; } case AUTHOR: { clauses.add(dao.createIndexClause("idx_author")); values.add(term); break; } case YEAR: { clauses.add(dao.createIndexClause("idx_year")); values.add(term); break; } case ISBN: { clauses.add(dao.createIndexClause("idx_isbn")); values.add(term); break; } case ISSN: { clauses.add(dao.createIndexClause("idx_isbn")); values.add(term); break; } case SERIAL: { clauses.add(dao.createSerialClause(term)); break; } case SUBJECT: { clauses.add(dao.createIndexClause("idx_subject")); values.add(term); break; } case TITLE: { clauses.add(dao.createIndexClause("idx_title")); values.add(term); break; } default: break; } } } String[] newBoolOpArr = new String[newBoolOp.size()]; newBoolOp.toArray(newBoolOpArr); final String clause = concatenateBooleanOperators(clauses, newBoolOpArr); result[0] = clause; result[1] = values; return result; } private String concatenateBooleanOperators(final ArrayList<String> clauses, final String[] boolOp) { if (clauses != null && !clauses.isEmpty()) { boolean notClause = false; final StringBuilder builder = new StringBuilder(); for (int i = 0; i < (clauses.size() - 1); i++) { String clause = clauses.get(i); if (notClause) { clause = clause.replaceAll("in \\(", "not in \\("); } builder.append(clause); if (boolOp[i].equals("AND_NOT")) { builder.append(" AND "); notClause = true; } else { builder.append(" ").append(boolOp[i]).append(" "); notClause = false; } } String clause = clauses.get(clauses.size() - 1); if (notClause) { clause = clause.replaceAll("in \\(", "not in \\("); } builder.append(clause); return builder.toString(); } return ""; } public RecordDTO getById(final int serial) { final BiblioDAO dao = new BiblioDAO(); return dao.getById(serial); } public RecordDTO getById(final String serial) { final BiblioDAO dao = new BiblioDAO(); return dao.getById(Integer.valueOf(serial)); } }