/* * Copyright (c) 2009-2010 Lockheed Martin Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * 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.eurekastreams.server.persistence; import java.util.Arrays; import java.util.HashMap; import java.util.List; import javax.persistence.Query; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eurekastreams.commons.hibernate.QueryOptimizer; import org.eurekastreams.server.domain.Organization; import org.eurekastreams.server.domain.strategies.OrganizationHierarchyTraverser; import org.eurekastreams.server.persistence.strategies.DescendantOrganizationStrategy; /** * This class provides the mapper functionality for Organization entities. * TODO quoted value of 'false' wasn't substituted correctly, * see https://forum.hibernate.org/viewtopic.php?f=1&t=1009876 */ @Deprecated public class OrganizationMapper extends DomainEntityMapper<Organization> implements CompositeEntityMapper { /** * The logger. */ private Log log = LogFactory.getLog(OrganizationMapper.class); /** * The descendant organization strategy. */ private DescendantOrganizationStrategy descendantOrgStrategy; /** * Constructor. * * @param inQueryOptimizer * the QueryOptimizer to use for specialized functions. */ public OrganizationMapper(final QueryOptimizer inQueryOptimizer) { super(inQueryOptimizer); } /** * Set the DescendantOrgStrategy. * * @param inDescendantOrgStrategy * the descendantOrgStrategy to set */ public void setDescendantOrgStrategy(final DescendantOrganizationStrategy inDescendantOrgStrategy) { descendantOrgStrategy = inDescendantOrgStrategy; } /** * Get the descendant organization strategy. * * @return the descendantOrgStrategy the descendant org strategy */ protected DescendantOrganizationStrategy getDescendantOrgStrategy() { if (descendantOrgStrategy == null) { throw new NullPointerException( "descendantOrgStrategy is null - make sure to set it on JpaOrganizationMapper."); } return descendantOrgStrategy; } /** * Retrieve the name of the DomainEntity. This is to allow for the super class to identify the table within * hibernate. * * @return The name of the domain entity. */ @Override protected String getDomainEntityName() { return "Organization"; } /** * Find by name. * * @param inName * the name of the user to search for * @return the Org with the account name. */ @SuppressWarnings("unchecked") public Organization findByShortName(final String inName) { Query q = getEntityManager().createQuery("from Organization where shortname = :inName").setParameter("inName", inName.toLowerCase()); List results = q.getResultList(); return (results.size() == 0) ? null : (Organization) results.get(0); } /** * Gets list of child organizations for a given organization. * * @param parentOrgId * Id of parent org. * @return List of child organizations for a given organization. */ public List<Organization> getDescendantOrganizations(final long parentOrgId) { return descendantOrgStrategy.getDescendantOrganizations(parentOrgId); } /** * Return the root of the organization tree, this is indicated by an org that has itself as it's parent. * * @return The root of the organization tree. */ @SuppressWarnings("unchecked") public Organization getRootOrganization() { Query q = getEntityManager().createQuery("FROM Organization o where o.parentOrganization.id=o.id"); List results = q.getResultList(); return (results.size() == 0) ? null : (Organization) results.get(0); } /** * Delete the organization with the input id. * * @param orgId * the organization id * @throws Exception * on error */ public void delete(final long orgId) throws Exception { // TODO: implement this - or remove it from the interface if this is not // a supported feature. // NOTE: to preserve the descendantOrganizationCount, this should call: // updateChildOrgCounts([parentId]); } /** * Update all of the denormalized statistics for a set of organizations. * * @param orgTraverser * the {@link OrganizationHierarchyTraverser} to use to get the organizations to traverse. This ensures * that all parent organizations are handled appropriately and efficiently. */ public void updateOrganizationStatistics(final OrganizationHierarchyTraverser orgTraverser) { long start = 0; if (log.isInfoEnabled()) { start = System.currentTimeMillis(); log.info("Updating the organization's statistics for a total of " + orgTraverser.getOrganizations().size() + " organizations: " + Arrays.toString(orgTraverser.getOrganizations().toArray())); } // the descendant org strategy uses a cached list to prevent unnecessary // queries HashMap<String, String> descOrgStringCache = new HashMap<String, String>(); for (Organization org : orgTraverser.getOrganizations()) { log.info("Inspecting org: " + org.toString()); // update recursive counts String descendantOrgIdString = descendantOrgStrategy.getDescendantOrganizationIdsForJpql(org.getId(), descOrgStringCache); updateDescendantEmployeeCount(org, descendantOrgIdString); updateDescendantGroupCount(org, descendantOrgIdString); // update non-recursive counts updateChildOrganizationCount(org); } getEntityManager().flush(); if (log.isInfoEnabled()) { log.info("Completed updating the organization's statistics for orgs in " + (System.currentTimeMillis() - start) + " milliseconds"); } } /** * Update an organization's child (non-recursive) organization count. * * @param inOrg * The org to update. */ public void updateChildOrganizationCount(final Organization inOrg) { String queryString = "SELECT count(*) FROM Organization WHERE " + "parentOrganization.id = :orgId AND id != parentOrganization.id"; Query query = getEntityManager().createQuery(queryString); query.setParameter("orgId", inOrg.getId()); inOrg.setChildOrganizationCount(((Long) query.getSingleResult()).intValue()); } /** * Update an organization's descendant employee count. * * @param organization * the organization to update * @param descendantOrgIdString * the "1,2,3,4" string of organization ids including the input org and its descendants. */ private void updateDescendantEmployeeCount(final Organization organization, final String descendantOrgIdString) { Long descendantEmpCount = (Long) getEntityManager().createQuery( "select count(distinct id) from Person where parentOrganization.id IN (" + descendantOrgIdString + ")").getSingleResult(); int descendantEmployeeCount = descendantEmpCount.intValue(); if (log.isInfoEnabled()) { log.info("Org id #" + organization.getId() + " has " + descendantEmployeeCount + " descendant employees"); } organization.setDescendantEmployeeCount(descendantEmployeeCount); } /** * Update an organization's descendant domain group count. * * @param organization * the organization to update * @param descendantOrgIdString * the "1,2,3,4" string of organization ids including the input org and its descendants. */ private void updateDescendantGroupCount(final Organization organization, final String descendantOrgIdString) { Long descendantGroupCount = (Long) getEntityManager().createQuery( "select count(distinct id) from DomainGroup where parentOrganization.id IN (" + descendantOrgIdString + ") and isPending=false").getSingleResult(); int descendantDomainGroupCount = descendantGroupCount.intValue(); if (log.isInfoEnabled()) { log.info("Org id #" + organization.getId() + " has " + descendantDomainGroupCount + " descendant domain groups"); } organization.setDescendantGroupCount(descendantDomainGroupCount); } }