/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.ofbiz.content;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.StringUtil;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.base.util.collections.LifoSet;
import org.apache.ofbiz.content.content.ContentServicesComplex;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntity;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericPK;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.condition.EntityOperator;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtil;
import org.apache.ofbiz.entityext.permission.EntityPermissionChecker;
import org.apache.ofbiz.minilang.MiniLangException;
import org.apache.ofbiz.security.Security;


/**
 * ContentManagementWorker Class
 */
public final class ContentManagementWorker {

    public static final String module = ContentManagementWorker.class.getName();
    private static Map<String, GenericValue> cachedWebSitePublishPoints = new HashMap<String, GenericValue>();
    private static Map<String, Map<String, Object>> cachedStaticValues = new HashMap<String, Map<String,Object>>();

    private ContentManagementWorker() {}

    public static void mruAdd(HttpServletRequest request, GenericEntity pk, String suffix) {
        HttpSession session = request.getSession();
        mruAdd(session, pk);
    }

    public static void mruAdd(HttpServletRequest request, GenericEntity pk) {
        HttpSession session = request.getSession();
        mruAdd(session, pk);
    }

    public static void mruAdd(HttpSession session, GenericEntity pk) {
        if (pk == null) {
            return;
        }

        Map<String, LifoSet<Object>> lookupCaches = UtilGenerics.checkMap(session.getAttribute("lookupCaches"));
        if (lookupCaches == null) {
            lookupCaches = new HashMap<String, LifoSet<Object>>();
            session.setAttribute("lookupCaches", lookupCaches);
        }
        String entityName = pk.getEntityName();
        mruAddByEntityName(entityName, pk, lookupCaches);
    }

   /**
    * Makes an entry in the "most recently used" cache. It picks the cache
    * by the entity name and builds a signature from the primary key values.
    *
    * @param entityName
    * @param lookupCaches
    * @param pk either a GenericValue or GenericPK - populated
    */
    public static void mruAddByEntityName(String entityName, GenericEntity pk, Map<String, LifoSet<Object>> lookupCaches) {
        String cacheEntityName = entityName;
        LifoSet<Object> lkupCache = lookupCaches.get(cacheEntityName);
        if (lkupCache == null) {
            lkupCache = new LifoSet<Object>();
            lookupCaches.put(cacheEntityName, lkupCache);
        }
        lkupCache.add(pk.getPrimaryKey());
        if (Debug.infoOn()) Debug.logInfo("in mruAddByEntityName, entityName:" + entityName + " lifoSet.size()" + lkupCache.size(), module);
    }

    public static Iterator<Object> mostRecentlyViewedIterator(String entityName, Map<String, LifoSet<Object>> lookupCaches) {
        String cacheEntityName = entityName;
        LifoSet<Object> lkupCache = lookupCaches.get(cacheEntityName);
        if (lkupCache == null) {
            lkupCache = new LifoSet<Object>();
            lookupCaches.put(cacheEntityName, lkupCache);
        }

        Iterator<Object> mrvIterator = lkupCache.iterator();
        return mrvIterator;
    }


   /**
    * Builds a string signature from a GenericValue or GenericPK.
    *
    * @param pk either a populated GenericValue or GenericPK.
    * @param suffix a string that can be used to distinguish the signature (probably not used).
    */
    public static String buildPKSig(GenericEntity pk, String suffix) {
        StringBuilder sig = new StringBuilder("");
        Collection<String> keyColl = pk.getPrimaryKey().getAllKeys();
        List<String> keyList = UtilMisc.makeListWritable(keyColl);
        Collections.sort(keyList);
        for (String ky : keyList) {
            String val = (String)pk.get(ky);
            if (UtilValidate.isNotEmpty(val)) {
                if (sig.length() > 0) sig.append("_");
                sig.append(val);
            }
        }
        if (UtilValidate.isNotEmpty(suffix)) {
            if (sig.length() > 0) sig.append("_");
            sig.append(suffix);
        }
        return sig.toString();
    }

    public static void setCurrentEntityMap(HttpServletRequest request, GenericEntity ent) {
        String entityName = ent.getEntityName();
        setCurrentEntityMap(request, entityName, ent);
    }

    public static void setCurrentEntityMap(HttpServletRequest request, String entityName, GenericEntity ent) {
        HttpSession session = request.getSession();
        Map<String, GenericEntity> currentEntityMap = UtilGenerics.checkMap(session.getAttribute("currentEntityMap"));
        if (currentEntityMap == null) {
            currentEntityMap = new HashMap<String, GenericEntity>();
            session.setAttribute("currentEntityMap", currentEntityMap);
        }
        currentEntityMap.put(entityName, ent);
    }

    public static String getFromSomewhere(String name, Map<String, Object> paramMap, HttpServletRequest request, Map<String, Object> context) {
        String ret = null;
        if (paramMap != null) {
            ret = (String)paramMap.get(name);
        }
        if (UtilValidate.isEmpty(ret)) {
            Object obj = request.getAttribute(name);
            if (obj != null) {
                ret = obj.toString();
            } else {
                obj = context.get(name);
                if (obj != null) {
                    ret = obj.toString();
                }
            }
        }
        return ret;
    }

    public static void getCurrentValue(HttpServletRequest request, Delegator delegator) {
        HttpSession session = request.getSession();
        Map<String, GenericPK> currentEntityMap = UtilGenerics.checkMap(session.getAttribute("currentEntityMap"));
        if (currentEntityMap == null) {
            currentEntityMap = new HashMap<String, GenericPK>();
            session.setAttribute("currentEntityMap", currentEntityMap);
        }
        Map<String, Object> paramMap = UtilHttp.getParameterMap(request);
        String entityName = (String)paramMap.get("entityName");
        if (UtilValidate.isEmpty(entityName)) {
            entityName = (String)request.getAttribute("entityName");
        }
        GenericPK cachedPK = null;
        if (UtilValidate.isNotEmpty(entityName)) {
            cachedPK = currentEntityMap.get(entityName);
        } 
        getCurrentValueWithCachedPK(request, delegator, cachedPK, entityName);
        GenericPK currentPK = (GenericPK)request.getAttribute("currentPK");
        currentEntityMap.put(entityName, currentPK);
    }

    public static void getCurrentValueWithCachedPK(HttpServletRequest request, Delegator delegator, GenericPK cachedPK, String entityName) {
        Map<String, Object> paramMap = UtilHttp.getParameterMap(request);
        // Build the primary key that may have been passed in as key values
        GenericValue v = delegator.makeValue(entityName);
        GenericPK passedPK = v.getPrimaryKey();
        Collection<String> keyColl = passedPK.getAllKeys();
        for (String attrName : keyColl) {
            String attrVal = (String)request.getAttribute(attrName);
            if (UtilValidate.isEmpty(attrVal)) {
                attrVal = (String)paramMap.get(attrName);
            }
            if (UtilValidate.isNotEmpty(attrVal)) {
                passedPK.put(attrName,attrVal);
            }
        }

        // If a full passed primary key exists, it takes precedence over a cached key
        // I cannot determine if the key testing utils of GenericEntity take into account
        // whether or not a field is populated.
        boolean useCached = false;
        boolean usePassed = true;
        if (cachedPK != null) {
            useCached = true;
            keyColl = cachedPK.getPrimaryKey().getAllKeys();
            for (String ky : keyColl) {
                String sCached = null;
                String sPassed = null;
                Object oPassed = null;
                Object oCached = null;
                oPassed = passedPK.get(ky);
                if (oPassed != null) {
                    sPassed = oPassed.toString();
                    if (UtilValidate.isEmpty(sPassed)) {
                        // If any part of passed key is not available, it can't be used
                        usePassed = false;
                    } else {
                        oCached = cachedPK.get(ky);
                        if (oCached != null) {
                            sCached = oCached.toString();
                            if (UtilValidate.isEmpty(sCached)) {
                                useCached = false;
                            } else {
                            }
                        } else {
                            useCached = false;
                        }
                    }
                } else {
                    usePassed = false;
                }
            }
        }

        GenericPK currentPK = null;
        if (usePassed && useCached) {
            currentPK = passedPK;
        } else if (usePassed && !useCached) {
            currentPK = passedPK;
        } else if (!usePassed && useCached) {
            currentPK = cachedPK;
        }

        if (currentPK != null) {
            request.setAttribute("currentPK", currentPK);
            GenericValue currentValue = null;
            try {
                currentValue = EntityQuery.use(delegator).from(currentPK.getEntityName()).where(currentPK).queryOne();
            } catch (GenericEntityException e) {
            }
            request.setAttribute("currentValue", currentValue);
        }

    }

    public static List<String []> getPermittedPublishPoints(Delegator delegator, List<GenericValue> allPublishPoints, GenericValue userLogin, Security security, String permittedAction, String permittedOperations, String passedRoles) throws GeneralException {
        List<String []> permittedPublishPointList = new LinkedList<String[]>();

        // Check that user has permission to admin sites
        for (GenericValue webSitePP : allPublishPoints) {
            String contentId = (String)webSitePP.get("contentId");
            String templateTitle = (String)webSitePP.get("templateTitle");
            GenericValue content = delegator.makeValue("Content", UtilMisc.toMap("contentId", contentId));
            String statusId = null;
            String entityAction = permittedAction;
            if (entityAction == null) {
                entityAction = "_ADMIN";
            }
            List<String> passedPurposes = UtilMisc.toList("ARTICLE");
            List<String> roles = StringUtil.split(passedRoles, "|");
            List<String> targetOperationList = new LinkedList<String>();
            if (UtilValidate.isEmpty(permittedOperations)) {
                 targetOperationList.add("CONTENT" + entityAction);
            } else {
                 targetOperationList = StringUtil.split(permittedOperations, "|");
            }
            Map<String, Object> results = null;
            results = EntityPermissionChecker.checkPermission(content, statusId, userLogin, passedPurposes, targetOperationList, roles, delegator, security, entityAction);
            String permissionStatus = (String)results.get("permissionStatus");
            if (permissionStatus != null && permissionStatus.equalsIgnoreCase("granted")) {
                String [] arr = {contentId,templateTitle};
                permittedPublishPointList.add(arr);
            }
        }
        return permittedPublishPointList;
    }

    /**
     Returns a list of WebSitePublishPoint entities that are children of parentPubPt
     The name should be "getAllTopLevelPublishPoints" or "getAllChildPublishPoints"

     @param parentPubPt The parent publish point.
     */
    public static List<GenericValue> getAllPublishPoints(Delegator delegator, String parentPubPt) throws GeneralException {
        List<GenericValue> relatedPubPts = null;
        try {
            relatedPubPts = EntityQuery.use(delegator).from("ContentAssoc")
                    .where("contentIdTo", parentPubPt, "contentAssocTypeId", "SUBSITE")
                    .cache().queryList();
        } catch (GenericEntityException e) {
            throw new GeneralException(e.getMessage());
        }
        List<GenericValue> allPublishPoints = new LinkedList<GenericValue>();
        GenericValue webSitePublishPoint = null;
        for (GenericValue contentAssoc : relatedPubPts) {
           String pub = (String)contentAssoc.get("contentId");
           webSitePublishPoint = getWebSitePublishPoint(delegator, pub, false);
           allPublishPoints.add(webSitePublishPoint);
        }
        return allPublishPoints;
    }

    public static Map<String, GenericValue> getPublishPointMap(Delegator delegator, String pubPtId) throws GeneralException {
        List<GenericValue> publishPointList = getAllPublishPoints(delegator, pubPtId);
        Map<String, GenericValue> publishPointMap = new HashMap<String, GenericValue>();
        for (GenericValue webSitePublishPoint : publishPointList) {
           String pub = (String)webSitePublishPoint.get("contentId");
           publishPointMap.put(pub, webSitePublishPoint);
        }
        return publishPointMap;
    }


    public static void getAllPublishPointMap(Delegator delegator, String pubPtId, Map<String, GenericValue> publishPointMap) throws GeneralException {
        List<GenericValue> publishPointList = getAllPublishPoints(delegator, pubPtId);
        for (GenericValue webSitePublishPoint : publishPointList) {
           String pub = (String)webSitePublishPoint.get("contentId");
           publishPointMap.put(pub, webSitePublishPoint);
           getAllPublishPointMap(delegator, pub, publishPointMap);
        }
    }

    public static Map<String, GenericValue> getPublishPointMap(Delegator delegator, List<GenericValue> publishPointList) {
        Map<String, GenericValue> publishPointMap = new HashMap<String, GenericValue>();
        for (GenericValue webSitePublishPoint : publishPointList) {
           String pub = (String)webSitePublishPoint.get("contentId");
           publishPointMap.put(pub, webSitePublishPoint);
        }
        return publishPointMap;
    }

    public static List<Map<String, Object>> getStaticValues(Delegator delegator,  String parentPlaceholderId, List<String []> permittedPublishPointList) throws GeneralException {
        List<GenericValue> assocValueList = null;
        try {
            assocValueList = EntityQuery.use(delegator).from("Content").where("contentTypeId", parentPlaceholderId).cache().queryList();
        } catch (GenericEntityException e) {
            throw new GeneralException(e.getMessage());
        }

        List<Map<String, Object>> staticValueList = new LinkedList<Map<String,Object>>();
        int counter = 0;
        for (GenericValue content : assocValueList) {
            String contentId = (String)content.get("contentId");
            String contentName = (String)content.get("contentName");
            String description = (String)content.get("description");
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("contentId", contentId);
            map.put("contentName", contentName);
            map.put("description", description);
            for (String [] publishPointArray : permittedPublishPointList) {
                String publishPointId = publishPointArray[0];
                List<GenericValue> contentAssocList = content.getRelated("ToContentAssoc", UtilMisc.toMap("contentId", publishPointId), null, false);
                List<GenericValue> filteredList = EntityUtil.filterByDate(contentAssocList);
                if (filteredList.size() > 0) {
                    map.put(publishPointId, "Y");
                    GenericValue assoc = filteredList.get(0);
                    Timestamp fromDate = (Timestamp)assoc.get("fromDate");
                    map.put(publishPointId + "FromDate", fromDate);
                } else {
                    map.put(publishPointId, "N");
                }
            }
            staticValueList.add(map);
            counter++;
        }
        return staticValueList;
    }

    public static GenericValue getWebSitePublishPoint(Delegator delegator, String contentId) throws GenericEntityException {
           return getWebSitePublishPoint(delegator, contentId, false);
    }

    public static GenericValue getWebSitePublishPoint(Delegator delegator, String contentId, boolean ignoreCache) throws GenericEntityException {
        GenericValue webSitePublishPoint = null;
        if (!ignoreCache)
            webSitePublishPoint = cachedWebSitePublishPoints.get(contentId);

        if (webSitePublishPoint == null) {
            webSitePublishPoint = EntityQuery.use(delegator).from("WebSitePublishPoint").where("contentId", contentId).queryOne();
            // If no webSitePublishPoint exists, still try to look for parent by making a dummy value
            if (webSitePublishPoint == null) {
                webSitePublishPoint = delegator.makeValue("WebSitePublishPoint", UtilMisc.toMap("contentId", contentId));
            }
            webSitePublishPoint = overrideWebSitePublishPoint(delegator, webSitePublishPoint);
            cachedWebSitePublishPoints.put(contentId, webSitePublishPoint);
        }
        return webSitePublishPoint;
    }

    public static GenericValue overrideWebSitePublishPoint(Delegator delegator, GenericValue passedValue) throws GenericEntityException {
        String contentId = passedValue.getString("contentId");
        GenericValue webSitePublishPoint = passedValue;
        String contentIdTo = getParentWebSitePublishPointId(delegator, contentId);
        if (contentIdTo != null) {
            webSitePublishPoint = EntityQuery.use(delegator).from("WebSitePublishPoint").where("contentId", contentIdTo).cache().queryOne();
            if (webSitePublishPoint != null) {
                webSitePublishPoint = GenericValue.create(webSitePublishPoint);
                webSitePublishPoint = overrideWebSitePublishPoint(delegator, webSitePublishPoint);
                webSitePublishPoint.setNonPKFields(passedValue, false);
                webSitePublishPoint.setPKFields(passedValue, false);
                passedValue.setNonPKFields(webSitePublishPoint);
            }
        }
        return webSitePublishPoint;
    }

    public static GenericValue getParentWebSitePublishPointValue(Delegator delegator, String  contentId) throws GenericEntityException {

        String contentIdTo = getParentWebSitePublishPointId(delegator, contentId);
        GenericValue content = EntityQuery.use(delegator).from("Content").where("contentId", contentIdTo).cache().queryOne();
        return content;
    }

    public static String getParentWebSitePublishPointId(Delegator delegator, String  contentId) throws GenericEntityException {
        String contentIdTo = null;
        GenericValue contentAssoc = EntityQuery.use(delegator).from("ContentAssoc")
                .where("contentId", contentId, "contentAssocTypeId", "SUBSITE")
                .filterByDate().cache().queryFirst();
        if (contentAssoc != null) {
            contentIdTo = contentAssoc.getString("contentIdTo");
        }
        return contentIdTo;
    }

    public static GenericValue getStaticValue(Delegator delegator, String parentPlaceholderId, String webSitePublishPointId, boolean ignoreCache) throws GenericEntityException {
        GenericValue webSitePublishPoint = null;
        if (!ignoreCache) {
            Map<String, Object> subStaticValueMap = cachedStaticValues.get(parentPlaceholderId);
            if (subStaticValueMap == null) {
                subStaticValueMap = new HashMap<String, Object>();
                cachedStaticValues.put(parentPlaceholderId, subStaticValueMap);
            }
        }

        return webSitePublishPoint;
    }

    public static List<Object []> getPublishedLinks(Delegator delegator,  String targContentId, String rootPubId, GenericValue userLogin, Security security, String permittedAction, String permittedOperations , String passedRoles) throws GeneralException {
        // Set up one map with all the top-level publish points (to which only one sub point can be attached to)
        // and another map (publishPointMapAll) that points to one of the top-level points.
        List<GenericValue> allPublishPointList = getAllPublishPoints(delegator, rootPubId);
        List<String []> publishPointList = getPermittedPublishPoints(delegator, allPublishPointList, userLogin, security , permittedAction, permittedOperations, passedRoles);
        Map<String, Object> publishPointMap = new HashMap<String, Object>();
        Map<String, Object> publishPointMapAll = new HashMap<String, Object>();
        for (String [] arr : publishPointList) {
            String contentId = arr[0];
            String description = arr[1];
            List<Object []> subPointList = new LinkedList<Object[]>();
            Object nullObj = null;
            Object [] subArr = {contentId, subPointList, description, nullObj};
            publishPointMap.put(contentId, subArr);
            publishPointMapAll.put(contentId, contentId);
            List<GenericValue> subPublishPointList = getAllPublishPoints(delegator, contentId);
            for (GenericValue webSitePublishPoint2 : subPublishPointList) {
                String contentId2 = (String)webSitePublishPoint2.get("contentId");
                String description2 = (String)webSitePublishPoint2.get("templateTitle");
                publishPointMapAll.put(contentId2, contentId);
                Timestamp obj = null;
                Object [] subArr2 = {contentId2, description2, obj};
                subPointList.add(subArr2);
            }
        }
        List<GenericValue> assocValueList = null;
        try {
            assocValueList = EntityQuery.use(delegator).from("ContentAssoc")
                    .where("contentId", targContentId, "contentAssocTypeId", "PUBLISH_LINK")
                    .filterByDate().cache().queryList();
        } catch (GenericEntityException e) {
            throw new GeneralException(e.getMessage());
        }
        for (GenericValue contentAssoc : assocValueList) {
            String contentIdTo = contentAssoc.getString("contentIdTo");
            String topContentId = (String)publishPointMapAll.get(contentIdTo);
            Object [] subArr = (Object [])publishPointMap.get(topContentId);
            if (contentIdTo.equals(topContentId)) {
                subArr[3] =  contentAssoc.get("fromDate");
            } else {
                if (subArr != null) {
                    List<Object []> subPointList = UtilGenerics.checkList(subArr[1]);
                    Iterator<Object []> it5 = subPointList.iterator();
                    Object [] subArr2 = null;
                    while (it5.hasNext()) {
                        subArr2 = it5.next();
                        String contentId5 = (String)subArr2[0];
                        if (contentId5.equals(contentIdTo))
                            break;
                    }
                    subArr2[2] =  contentAssoc.get("fromDate");
                }
            }
        }

        List<Object []> publishedLinkList = new LinkedList<Object[]>();
        for (String contentId : publishPointMap.keySet()) {
            Object [] subPointArr = (Object [])publishPointMap.get(contentId);
            publishedLinkList.add(subPointArr);
        }
        return publishedLinkList;
    }

    public static GenericValue getAuthorContent(Delegator delegator, String contentId) {
        GenericValue authorContent = null;
        try {
            List<String> assocTypes = UtilMisc.toList("AUTHOR");
            List<String> contentTypes = null;
            Map<String, Object> results =  ContentServicesComplex.getAssocAndContentAndDataResourceCacheMethod(delegator, contentId, null, "To", null, null, assocTypes, contentTypes, Boolean.TRUE, null, null);
            List<GenericValue> valueList = UtilGenerics.checkList(results.get("entityList"));
            if (valueList.size() > 0) {
                GenericValue value = valueList.get(0);
                authorContent = delegator.makeValue("Content");
                authorContent.setPKFields(value);
                authorContent.setNonPKFields(value);
            }
        } catch (GenericEntityException e) {
        } catch (MiniLangException e2) {
        }

        return authorContent;
    }

    public static List<String []> getPermittedDepartmentPoints(Delegator delegator, List<GenericValue> allDepartmentPoints, GenericValue userLogin, Security security, String permittedAction, String permittedOperations, String passedRoles) throws GeneralException {
        List<String []> permittedDepartmentPointList = new LinkedList<String[]>();

        // Check that user has permission to admin sites
        for (GenericValue content : allDepartmentPoints) {
            String contentId = (String)content.get("contentId");
            String contentName = (String)content.get("contentName");
            String statusId = null;
            String entityAction = permittedAction;
            if (entityAction == null)
                entityAction = "_ADMIN";
            List<String> passedPurposes = UtilMisc.<String>toList("ARTICLE");
            List<String> roles = StringUtil.split(passedRoles, "|");
            List<String> targetOperationList = new LinkedList<String>();
            if (UtilValidate.isEmpty(permittedOperations)) {
                 targetOperationList.add("CONTENT" + entityAction);
            } else {
                 targetOperationList = StringUtil.split(permittedOperations, "|");
            }
            Map<String, Object> results = null;
            results = EntityPermissionChecker.checkPermission(content, statusId, userLogin, passedPurposes, targetOperationList, roles, delegator, security, entityAction);
            String permissionStatus = (String)results.get("permissionStatus");
            if (permissionStatus != null && permissionStatus.equalsIgnoreCase("granted")) {
                String [] arr = {contentId,contentName};
                permittedDepartmentPointList.add(arr);
            }
        }
        return permittedDepartmentPointList;
    }

    /**
     Returns a list of "department" (having ContentAssoc of type "DEPARTMENT")
     Content entities that are children of parentPubPt

     @param parentPubPt The parent publish point.
     */
    public static List<GenericValue> getAllDepartmentContent(Delegator delegator, String parentPubPt) throws GeneralException {
        List<GenericValue> relatedPubPts = null;
        try {
            relatedPubPts = EntityQuery.use(delegator).from("ContentAssoc")
                    .where("contentIdTo", parentPubPt, "contentAssocTypeId", "DEPARTMENT")
                    .cache().queryList();

        } catch (GenericEntityException e) {
            throw new GeneralException(e.getMessage());
        }
        List<GenericValue> allDepartmentPoints = new LinkedList<GenericValue>();
        GenericValue departmentContent = null;
        for (GenericValue contentAssoc : relatedPubPts) {
           String pub = (String)contentAssoc.get("contentId");
           departmentContent = EntityQuery.use(delegator).from("Content").where("contentId", pub).cache().queryOne();
           allDepartmentPoints.add(departmentContent);
        }
        return allDepartmentPoints;
    }

    public static String getUserName(HttpServletRequest request, String userLoginId) throws GenericEntityException {
        String userName = null;
        Delegator delegator = (Delegator)request.getAttribute("delegator");
        GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).cache().queryOne();
        GenericValue person = userLogin.getRelatedOne("Person", true);
        userName = person.getString("firstName") + " " + person.getString("lastName");
        return userName;
    }

    public static int updateStatsTopDown(Delegator delegator, String contentId, List<String> typeList) throws GenericEntityException {
        int subLeafCount = 0;
        GenericValue thisContent = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
        if (thisContent == null)
            throw new RuntimeException("No entity found for id=" + contentId);

       List<EntityCondition> conditionMain = new ArrayList<EntityCondition>();
       conditionMain.add(EntityCondition.makeCondition("contentIdTo", contentId));
       if (typeList.size() > 0) {
           conditionMain.add(EntityCondition.makeCondition("contentAssocTypeId", EntityOperator.IN, typeList));
       }
       List<GenericValue> contentAssocs = EntityQuery.use(delegator).from("ContentAssoc").where(conditionMain)
               .filterByDate().cache().queryList();
       for (GenericValue contentAssoc : contentAssocs) {
           String subContentId = contentAssoc.getString("contentId");
           subLeafCount += updateStatsTopDown(delegator, subContentId, typeList);
       }

        // If no children, count this as a leaf
        if (subLeafCount == 0)
            subLeafCount = 1;
        thisContent.put("childBranchCount", Long.valueOf(contentAssocs.size()));
        thisContent.put("childLeafCount", Long.valueOf(subLeafCount));
        thisContent.store();

        return subLeafCount;
    }

    public static void updateStatsBottomUp(Delegator delegator, String contentId, List<String> typeList, int branchChangeAmount, int leafChangeAmount) throws GenericEntityException {
        GenericValue thisContent = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
        if (thisContent == null)
            throw new RuntimeException("No entity found for id=" + contentId);

        List<GenericValue> contentAssocs = EntityQuery.use(delegator).from("ContentAssoc")
                .where(EntityCondition.makeCondition("contentAssocTypeId", EntityOperator.IN, typeList),
                        EntityCondition.makeCondition("contentId", EntityOperator.EQUALS, contentId))
                .cache().filterByDate().queryList();
        for (GenericValue contentAssoc : contentAssocs) {
            String contentIdTo = contentAssoc.getString("contentIdTo");
            GenericValue contentTo = EntityQuery.use(delegator).from("Content").where("contentId", contentIdTo).queryOne();
            int intLeafCount = 0;
            Long leafCount = (Long)contentTo.get("childLeafCount");
            if (leafCount != null) {
                intLeafCount = leafCount.intValue();
            }
            contentTo.set("childLeafCount", Long.valueOf(intLeafCount + leafChangeAmount));

            if (branchChangeAmount != 0) {
                int intBranchCount = 0;
                Long branchCount = (Long)contentTo.get("childBranchCount");
                if (branchCount != null) {
                    intBranchCount = branchCount.intValue();
                }
                contentTo.set("childBranchCount", Long.valueOf(intBranchCount + branchChangeAmount));
            }
            contentTo.store();
            updateStatsBottomUp(delegator, contentIdTo, typeList, 0, leafChangeAmount);
        }
    }
}
