/* * 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.strategies; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.eurekastreams.server.domain.Organization; /** * Strategy to recursively determine child organizations. */ public class DescendantOrganizationStrategy { /** * EntityManager to use for all ORM operations. */ private EntityManager entityManager; /** * Set the entity manager to use for all ORM operations. * * @param inEntityManager * the EntityManager to use for all ORM operations. */ @PersistenceContext public void setEntityManager(final EntityManager inEntityManager) { this.entityManager = inEntityManager; } /** * Get the org's id by its short name. * * @param inShortName * the org's short name * @return the org's id, or 0 if not found */ public long getOrgIdByShortName(final String inShortName) { Query q = entityManager.createQuery("SELECT id FROM Organization WHERE shortName = :shortName").setParameter( "shortName", inShortName); List<Long> orgIds = q.getResultList(); if (orgIds.size() != 1) { return 0; } return orgIds.get(0); } /** * Return a comma-separated list of IDs of all child organizations of the input parent organization id, including * the id of the passed-in org. * * @param parentOrgId * the parent organization id * @param descendantOrgIdMap * hashmap to use for caching query results - this method will most likely be called in a loop, so * prevent senseless queries for the same descendant counts. * @return a comma-separated list of IDs of all child organizations of the input parent organization id */ public String getDescendantOrganizationIdsForJpql(final long parentOrgId, final HashMap<String, String> descendantOrgIdMap) { return getDescendantOrganizationIdsForJpql(Long.toString(parentOrgId), descendantOrgIdMap); } /** * Return a comma-separated list of IDs of the input and all child organizations of the input parent organization * ids. Flush is called at the top to make any local changes available to the JPQL. * * @param orgIds * comma-separated list of the IDs to get children for * @param descendantOrgIdMap * hashmap to use for caching query results - this method will most likely be called in a loop, so * prevent senseless queries for the same descendant counts. * @return a comma-separated list of IDs of all child organizations of the input parent organization id */ @SuppressWarnings("unchecked") public String getDescendantOrganizationIdsForJpql(final String orgIds, final HashMap<String, String> descendantOrgIdMap) { // use the cached hierarchy if we have it if (descendantOrgIdMap.containsKey(orgIds)) { return descendantOrgIdMap.get(orgIds); } entityManager.flush(); // note: the ordering is for unit testability Query q = entityManager.createQuery("SELECT id FROM Organization o where o.parentOrganization.id IN ( " + orgIds + ") and o.id<>o.parentOrganization.id order by id"); // flatten the list of longs into a comma-separated list of child org // ids String childOrgIds = ""; for (Long childOrgId : (List<Long>) q.getResultList()) { if (childOrgIds.length() > 0) { childOrgIds += ","; } childOrgIds += childOrgId; } // recurse String allOrgIds = orgIds; if (childOrgIds.length() > 0) { String result = getDescendantOrganizationIdsForJpql(childOrgIds, descendantOrgIdMap); if (result.length() > 0) { if (allOrgIds.length() > 0) { allOrgIds += ","; } allOrgIds += result; } } // cache this hierarchy descendantOrgIdMap.put(orgIds, allOrgIds); return allOrgIds; } /** * Gets list of child organizations for a given organization. * * @param parentOrgId * Id of parent org. * @return List of child organizations for a given organization. */ @SuppressWarnings("unchecked") public List<Organization> getDescendantOrganizations(final long parentOrgId) { Query q = entityManager.createQuery( "FROM Organization o where o.parentOrganization.id=:parentOrgId and o.id<>:parentOrgId").setParameter( "parentOrgId", parentOrgId); List<Organization> childOrgs = q.getResultList(); List<Organization> allOrgs = new ArrayList<Organization>(); // recursively add child organizations for (Organization org : childOrgs) { allOrgs.add(org); allOrgs.addAll(getDescendantOrganizations(org.getId())); } return allOrgs; } }