Java tutorial
/* ************************************************************************* * The contents of this file are subject to the Openbravo Public License * Version 1.1 (the "License"), being the Mozilla Public License * Version 1.1 with a permitted attribution clause; you may not use this * file except in compliance with the License. You may obtain a copy of * the License at http://www.openbravo.com/legal/license.html * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * The Original Code is Openbravo ERP. * The Initial Developer of the Original Code is Openbravo SLU * All portions are Copyright (C) 2009-2014 Openbravo SLU * All Rights Reserved. * Contributor(s): ______________________________________. ************************************************************************ */ package org.openbravo.service.json; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.hibernate.Query; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.openbravo.base.exception.OBException; import org.openbravo.base.model.Entity; import org.openbravo.base.model.ModelProvider; import org.openbravo.base.model.Property; import org.openbravo.base.model.domaintype.TableDomainType; import org.openbravo.base.structure.BaseOBObject; import org.openbravo.base.util.Check; import org.openbravo.client.kernel.KernelUtils; import org.openbravo.dal.core.DalUtil; import org.openbravo.dal.service.OBDal; import org.openbravo.dal.service.OBQuery; import org.openbravo.model.ad.datamodel.Column; /** * Implements a service which can handle different types of query and paging options. This class * supports standard parameters for paging and flexible parameters for filtering queries. Sorting is * supported on one property. * * This service class only supports querying for one {@link Entity}. * * This service class can not be used as a singleton. * * It makes use of the {@link QueryBuilder} helper class to manage filter information. * * @author mtaal */ public class DataEntityQueryService { private static final Logger log = Logger.getLogger(DataEntityQueryService.class); public static final String PARAM_DELIMITER = "@"; private String entityName; private Integer firstResult = null; private Integer maxResults = null; private boolean filterOnActive = true; private AdvancedQueryBuilder queryBuilder = new AdvancedQueryBuilder(); private boolean filterOnReadableOrganizations = true; private boolean filterOnReadableClients = true; private String distinct; private String summarySettings; private List<String> summaryFields = new ArrayList<String>(); /** * Count the records which fit in the filter criteria. * * @return the number of records in the filter. */ public int count() { Check.isNotNull(entityName, "entityName must be set"); final OBQuery<BaseOBObject> obq = OBDal.getInstance().createQuery(entityName, queryBuilder.getJoinClause() + queryBuilder.getWhereClause()); obq.setFilterOnReadableClients(isFilterOnReadableClients()); obq.setFilterOnReadableOrganization(isFilterOnReadableOrganizations()); if (queryBuilder.hasOrganizationParameter()) { obq.setFilterOnReadableOrganization(false); } if (!filterOnActive) { obq.setFilterOnActive(false); } obq.setNamedParameters(queryBuilder.getNamedParameters()); return obq.count(); } /** * Return the list of {@link BaseOBObject} objects retrieved by querying using the filter * criteria. * * @return the list of retrieved objects from the db. */ public List<BaseOBObject> list() { return buildOBQuery().list(); } /** * @return a result which can be scrolled forward only and the results are not cached */ public ScrollableResults scroll() { final Query qry = buildOBQuery().createQuery(); qry.setFetchSize(1000); qry.setCacheable(false); return qry.scroll(ScrollMode.FORWARD_ONLY); } /** * Build an OBQuery object using the generated where, order by and select clauses. */ public OBQuery<BaseOBObject> buildOBQuery() { final String whereOrderBy = queryBuilder.getJoinClause() + queryBuilder.getWhereClause() + (getSummarySettings() == null ? queryBuilder.getOrderByClause() : ""); log.debug("Querying for " + entityName + " " + whereOrderBy); final OBQuery<BaseOBObject> obq = OBDal.getInstance().createQuery(entityName, whereOrderBy); obq.setFilterOnReadableClients(isFilterOnReadableClients()); obq.setFilterOnReadableOrganization(isFilterOnReadableOrganizations()); if (getSummarySettings() != null) { obq.setSelectClause(queryBuilder.getSelectClause()); } if (getFirstResult() != null) { obq.setFirstResult(getFirstResult()); log.debug("Firstresult " + getFirstResult()); } if (getMaxResults() != null) { obq.setMaxResult(getMaxResults()); log.debug("Maxresult " + getMaxResults()); } if (queryBuilder.hasOrganizationParameter()) { obq.setFilterOnReadableOrganization(false); } obq.setFilterOnActive(isFilterOnActive()); if (log.isDebugEnabled()) { String params = ""; Map<String, Object> namedParams = queryBuilder.getNamedParameters(); for (String paramName : namedParams.keySet()) { params += " -" + paramName + ": " + namedParams.get(paramName) + "\n"; } log.debug("Setting params:\n" + params); } obq.setNamedParameters(queryBuilder.getNamedParameters()); return obq; } AdvancedQueryBuilder getQueryBuilder() { return queryBuilder; } // package private on purpose List<Property> getDistinctDisplayProperties() { final String localDistinct = getDistinct(); final List<Property> properties = new ArrayList<Property>(); final Property property = DalUtil .getPropertyFromPath(ModelProvider.getInstance().getEntity(getEntityName()), localDistinct); // now use the table reference definition or select on the identifier properties if (property.getDomainType() instanceof TableDomainType && ((TableDomainType) property.getDomainType()).getRefTable() != null) { final TableDomainType domainType = (TableDomainType) property.getDomainType(); final Property displayProp = KernelUtils.getInstance().getPropertyFromColumn( OBDal.getInstance().get(Column.class, domainType.getRefTable().getDisplayColumn().getId())); if (displayProp != null) { properties.add(displayProp); } } if (properties.isEmpty()) { for (Property identifierProp : property.getTargetEntity().getIdentifierProperties()) { properties.add(identifierProp); } } return properties; } public int getRowNumber(String targetRecordId) { final String whereOrderBy = queryBuilder.getJoinClause() + queryBuilder.getWhereClause() + queryBuilder.getOrderByClause(); log.debug("Querying for " + entityName + " " + whereOrderBy); final OBQuery<BaseOBObject> obq = OBDal.getInstance().createQuery(entityName, whereOrderBy); obq.setFilterOnReadableClients(isFilterOnReadableClients()); obq.setFilterOnReadableOrganization(isFilterOnReadableOrganizations()); if (queryBuilder.hasOrganizationParameter()) { obq.setFilterOnReadableOrganization(false); } obq.setFilterOnActive(isFilterOnActive()); obq.setNamedParameters(queryBuilder.getNamedParameters()); return obq.getRowNumber(targetRecordId); } public Integer getFirstResult() { return firstResult; } public void setFirstResult(Integer firstResult) { this.firstResult = firstResult; } public Integer getMaxResults() { return maxResults; } public void setMaxResults(Integer maxResults) { this.maxResults = maxResults; } public void setOrderBy(String orderBy) { queryBuilder.setOrderBy(orderBy); } public String getEntityName() { return entityName; } public void setEntityName(String entityName) { this.entityName = entityName; queryBuilder.setEntity(entityName); } /** * The text matching strategy used. See here for a description: * http://www.smartclient.com/docs/7.0rc2/a/b/c/go.html#attr..ComboBoxItem.textMatchStyle * * @param textMatchingName * the following values are allowed: startsWith, substring, exact */ public void setTextMatching(String textMatchingName) { } public void setCriteria(JSONObject criteria) { try { queryBuilder.setCriteria(criteria); if (criteria.has("operator") && AdvancedQueryBuilder.OPERATOR_OR.equals(criteria.getString("operator"))) { setDoOrExpression(); } } catch (JSONException e) { throw new OBException(e); } } public void addFilterParameter(String key, String value) { queryBuilder.addFilterParameter(key, value); } /** * If called then the where clause filters will be considered to be an or expression. */ public void setDoOrExpression() { queryBuilder.setDoOr(true); } /** * Tells the {@link QueryBuilder} to use the {@link JsonConstants#MAIN_ALIAS} as the alias for * prefixing all properties in the where clause and order by. */ public void setUseAlias() { queryBuilder.setMainAlias(JsonConstants.MAIN_ALIAS); } public boolean isFilterOnActive() { return filterOnActive; } public void setFilterOnActive(boolean filterOnActive) { this.filterOnActive = filterOnActive; } public void setJoinAssociatedEntities(boolean joinAssociatedEntities) { queryBuilder.setJoinAssociatedEntities(joinAssociatedEntities); } public void setAdditionalProperties(List<String> additionalProperties) { queryBuilder.setAdditionalProperties(additionalProperties); } public void clearCachedValues() { queryBuilder.clearCachedValues(); } public String getDistinct() { return distinct; } public void setDistinct(String distinct) { this.distinct = distinct.replace(DalUtil.FIELDSEPARATOR, DalUtil.DOT); } public String getSummarySettings() { return summarySettings; } public void setSummarySettings(String summarySettings) { this.summarySettings = summarySettings; if (getSummarySettings() != null) { try { summaryFields.clear(); final JSONObject summarySetting = new JSONObject(getSummarySettings()); final Iterator<?> it = summarySetting.keys(); while (it.hasNext()) { final String key = (String) it.next(); summaryFields.add(key); final String value = summarySetting.getString(key); queryBuilder.addSelectFunctionPart(value, key.replace(DalUtil.FIELDSEPARATOR, DalUtil.DOT)); } } catch (JSONException e) { throw new RuntimeException(e); } } } public List<String> getSummaryFields() { return summaryFields; } public boolean isFilterOnReadableOrganizations() { return filterOnReadableOrganizations; } public void setFilterOnReadableOrganizations(boolean filterOnReadableOrganizations) { this.filterOnReadableOrganizations = filterOnReadableOrganizations; } public boolean isFilterOnReadableClients() { return filterOnReadableClients; } public void setFilterOnReadableClients(boolean filterOnReadableClients) { this.filterOnReadableClients = filterOnReadableClients; } /** * In case of performing query for FK drop down list (ie. Organization link in Product window), * there are 2 entities to query: * <ul> * <li>main entity: in the example would be Organization which is the one we want to get records * from * <li>sub entity: in this case Product, it will be filtered in the same way it is in the grid so * only organizations with that criteria will be shown * </ul> */ void setSubEntity(String subEntityName, DataEntityQueryService dataEntityQueryService, Property distinctProperty, String distinctPropertyPath) { queryBuilder.setSubEntityName(subEntityName); queryBuilder.setSubDataEntityQueryService(dataEntityQueryService); queryBuilder.setDistinctProperty(distinctProperty); queryBuilder.setDistinctPropertyPath(distinctPropertyPath); } @Deprecated public void setSubEntity(String subEntityName, DataEntityQueryService dataEntityQueryService, Property distinctProperty) { setSubEntity(subEntityName, dataEntityQueryService, distinctProperty, distinctProperty.getName()); } }