/*******************************************************************************
 * 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.ofbiz.content;

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.sql.Timestamp;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastSet;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.cache.Cache;
import org.ofbiz.base.util.cache.UtilCache;
import org.ofbiz.content.content.ContentServices;
import org.ofbiz.content.content.ContentWorker;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.condition.EntityCondition;
import org.ofbiz.entity.condition.EntityOperator;
import org.ofbiz.entity.model.ModelUtil;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.security.Security;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceAuthException;
import org.ofbiz.service.ServiceUtil;

import com.ibm.icu.util.Calendar;

/**
 * ContentManagementServices Class
 */
public class ContentManagementServices {

    public static final String module = ContentManagementServices.class.getName();
    public static final String resource = "ContentUiLabels";

    /**
     * getSubContent
     * Finds the related subContent given the template Content and the mapKey.
     * This service calls a same-named method in ContentWorker to do the work.
     */
    public static Map<String, Object> getSubContent(DispatchContext dctx, Map<String, ? extends Object> context) {
        //Security security = dctx.getSecurity();
        Delegator delegator = dctx.getDelegator();
        //LocalDispatcher dispatcher = dctx.getDispatcher();
        String contentId = (String) context.get("contentId");
        String subContentId = (String) context.get("subContentId");
        String mapKey = (String) context.get("mapKey");
        GenericValue userLogin = (GenericValue)context.get("userLogin");
        Timestamp fromDate = (Timestamp)context.get("fromDate");
        List<String> assocTypes = UtilGenerics.checkList(context.get("assocTypes"));
        String assocTypesString = (String)context.get("assocTypesString");
        if (UtilValidate.isNotEmpty(assocTypesString)) {
            List<String> lst = StringUtil.split(assocTypesString, "|");
            if (assocTypes == null) {
                assocTypes = FastList.newInstance();
            }
            assocTypes.addAll(lst);
        }
        GenericValue content = null;
        GenericValue view = null;

        try {
            view = ContentWorker.getSubContentCache(delegator, contentId, mapKey, subContentId, userLogin, assocTypes, fromDate, Boolean.FALSE, null);
            content = ContentWorker.getContentFromView(view);
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        }

        Map<String, Object> results = ServiceUtil.returnSuccess();
        results.put("view", view);
        results.put("content", content);
        return results;
    }

    /**
     * getContent
     * This service calls a same-named method in ContentWorker to do the work.
     */
    public static Map<String, Object> getContent(DispatchContext dctx, Map<String, ? extends Object> context) {
        //Security security = dctx.getSecurity();
        Delegator delegator = dctx.getDelegator();
        String contentId = (String) context.get("contentId");
        //GenericValue userLogin = (GenericValue)context.get("userLogin");
        GenericValue view = null;

        try {
            view = ContentWorker.getContentCache(delegator, contentId);
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        }

        Map<String, Object> results = ServiceUtil.returnSuccess();
        results.put("view", view);
        return results;
    }

    /**
     * persistContentAndAssoc
     * A combination method that will create or update all or one of the following:
     * a Content entity, a ContentAssoc related to the Content, and
     * the ElectronicText that may be associated with the Content.
     * The keys for determining if each entity is created is the presence
     * of the contentTypeId, contentAssocTypeId and dataResourceTypeId.
     * This service tries to handle DataResource fields with and
     * without "dr" prefixes.
     * Assumes binary data is always in field, "imageData".
     *
     * This service does not accept straight ContentAssoc parameters. They must be prefaced with "ca" + cap first letter
     */
    public static Map<String, Object> persistContentAndAssoc(DispatchContext dctx, Map<String, ? extends Object> rcontext) throws GenericServiceException {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Map<String, Object> context = UtilMisc.makeMapWritable(rcontext);
        Locale locale = (Locale) context.get("locale");

        // Knowing why a request fails permission check is one of the more difficult
        // aspects of content management. Setting "displayFailCond" to true will
        // put an html table in result.errorMessage that will show what tests were performed
        Boolean bDisplayFailCond = (Boolean)context.get("displayFailCond");
        String mapKey = (String) context.get("mapKey");

        // If "deactivateExisting" is set, other Contents that are tied to the same
        // contentIdTo will be deactivated (thruDate set to now)
        String deactivateString = (String) context.get("deactivateExisting");
        boolean deactivateExisting = "true".equalsIgnoreCase(deactivateString);

        if (Debug.infoOn()) Debug.logInfo("in persist... mapKey(0):" + mapKey, null);

        // ContentPurposes can get passed in as a delimited string or a list. Combine.
        List<String> contentPurposeList = UtilGenerics.checkList(context.get("contentPurposeList"));
        if (contentPurposeList == null) {
            contentPurposeList = FastList.newInstance();
        }
        String contentPurposeString = (String) context.get("contentPurposeString");
        if (UtilValidate.isNotEmpty(contentPurposeString)) {
            List<String> tmpPurposes = StringUtil.split(contentPurposeString, "|");
            contentPurposeList.addAll(tmpPurposes);
        }
        if (contentPurposeList != null) {
            context.put("contentPurposeList", contentPurposeList);
            context.put("contentPurposeString", null);
        }
        
        if (Debug.infoOn()) {
            Debug.logInfo("in persist... contentPurposeList(0):" + contentPurposeList, null);
            Debug.logInfo("in persist... textData(0):" + context.get("textData"), null);
        }

        GenericValue content = delegator.makeValue("Content");
        
        content.setPKFields(context);
        content.setNonPKFields(context);
        String contentId = (String) content.get("contentId");
        String contentTypeId = (String) content.get("contentTypeId");
        String origContentId = (String) content.get("contentId");
        String origDataResourceId = (String) content.get("dataResourceId");
        
        if (Debug.infoOn()) {
            Debug.logInfo("in persist... contentId(0):" + contentId, null);
        }

        GenericValue dataResource = delegator.makeValue("DataResource");
        dataResource.setPKFields(context);
        dataResource.setNonPKFields(context);
        dataResource.setAllFields(context, false, "dr", null);
        String isPublic = (String) context.get("isPublic");
        if(UtilValidate.isEmpty(isPublic)){
            dataResource.set("isPublic", "N");
        }
        context.putAll(dataResource);
        String dataResourceId = (String) dataResource.get("dataResourceId");
        String dataResourceTypeId = (String) dataResource.get("dataResourceTypeId");
        if (Debug.infoOn()) {
            Debug.logInfo("in persist... dataResourceId(0):" + dataResourceId, null);
        }

        GenericValue contentAssoc = delegator.makeValue("ContentAssoc");
        String contentAssocTypeId = (String)context.get("contentAssocTypeId");
        if (UtilValidate.isNotEmpty(contentAssocTypeId)) {
            context.put("caContentAssocTypeId", contentAssocTypeId);
        }
        contentAssocTypeId = (String)context.get("caContentAssocTypeId");
        contentAssoc.setAllFields(context, false, "ca", null);
        contentAssoc.put("contentId", context.get("caContentId"));
        context.putAll(contentAssoc);

        GenericValue electronicText = delegator.makeValue("ElectronicText");
        electronicText.setPKFields(context);
        electronicText.setNonPKFields(context);

        // save expected primary keys on result now in case there is no operation that uses them
        Map<String, Object> results = ServiceUtil.returnSuccess();
        results.put("contentId", content.get("contentId"));
        results.put("dataResourceId", dataResource.get("dataResourceId"));
        results.put("drDataResourceId", dataResource.get("dataResourceId"));
        results.put("drDataResourceId", dataResource.get("dataResourceId"));
        results.put("caContentIdTo", contentAssoc.get("contentIdTo"));
        results.put("caContentId", contentAssoc.get("contentId"));
        results.put("caFromDate", contentAssoc.get("fromDate"));
        results.put("caContentAssocTypeId", contentAssoc.get("contentAssocTypeId"));

        // get user info for multiple use
        GenericValue userLogin = (GenericValue) context.get("userLogin");

        // TODO: DEJ20060221 Should these be used somewhere?
        //String textData = (String)electronicText.get("textData");

        //String userLoginId = (String)userLogin.get("userLoginId");

        //String createdByUserLogin = userLoginId;
        //String lastModifiedByUserLogin = userLoginId;
        //Timestamp createdDate = UtilDateTime.nowTimestamp();
        //Timestamp lastModifiedDate = UtilDateTime.nowTimestamp();

        // Do update and create permission checks on DataResource if warranted.
        //boolean updatePermOK = false;
        //boolean createPermOK = false;


        boolean dataResourceExists = true;
        if (Debug.infoOn()) {
            Debug.logInfo("in persist... dataResourceTypeId(0):" + dataResourceTypeId, null);
        }
        if (UtilValidate.isNotEmpty(dataResourceTypeId)) {
            Map<String, Object> dataResourceResult = FastMap.newInstance();
            try {
                dataResourceResult = persistDataResourceAndDataMethod(dctx, context);
            } catch (GenericServiceException e) {
                Debug.logError(e, e.toString(), module);
                return ServiceUtil.returnError(e.toString());
            } catch (GenericEntityException e) {
                Debug.logError(e, e.toString(), module);
                return ServiceUtil.returnError(e.toString());
            } catch (Exception e) {
                Debug.logError(e, e.toString(), module);
                return ServiceUtil.returnError(e.toString());
            }
            String errorMsg = ServiceUtil.getErrorMessage(dataResourceResult);
            if (UtilValidate.isNotEmpty(errorMsg)) {
                return ServiceUtil.returnError(errorMsg);
            }
            dataResourceId = (String)dataResourceResult.get("dataResourceId");
            results.put("dataResourceId", dataResourceId);
            results.put("drDataResourceId", dataResourceId);
            context.put("dataResourceId", dataResourceId);
            content.put("dataResourceId", dataResourceId);
            context.put("drDataResourceId", dataResourceId);
        }
        // Do update and create permission checks on Content if warranted.

        context.put("skipPermissionCheck", null);  // Force check here
        boolean contentExists = true;
        if (Debug.infoOn()) {
            Debug.logInfo("in persist... contentTypeId:" +  contentTypeId + " dataResourceTypeId:" + dataResourceTypeId + " contentId:" + contentId + " dataResourceId:" + dataResourceId, null);
        }
        if (UtilValidate.isNotEmpty(contentTypeId)) {
            if (UtilValidate.isEmpty(contentId)) {
                contentExists = false;
            } else {
                try {
                    GenericValue val = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
                    if (val == null) contentExists = false;
                } catch (GenericEntityException e) {
                    return ServiceUtil.returnError(e.toString());
                }
            }
            //List targetOperations = FastList.newInstance();
            //context.put("targetOperations", targetOperations);
            context.putAll(content);
            if (contentExists) {
                //targetOperations.add("CONTENT_UPDATE");
                Map<String, Object> contentContext = FastMap.newInstance();
                ModelService contentModel = dispatcher.getDispatchContext().getModelService("updateContent");
                contentContext.putAll(contentModel.makeValid(content, "IN"));
                contentContext.put("userLogin", userLogin);
                contentContext.put("displayFailCond", bDisplayFailCond);
                contentContext.put("skipPermissionCheck", context.get("skipPermissionCheck"));
                Debug.logInfo("In persistContentAndAssoc calling updateContent with content: " + contentContext, module);
                Map<String, Object> thisResult = dispatcher.runSync("updateContent", contentContext);
                if (ServiceUtil.isError(thisResult) || ServiceUtil.isFailure(thisResult)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentContentUpdatingError", UtilMisc.toMap("serviceName", "persistContentAndAssoc"), locale), null, null, thisResult);
                }
                //Map thisResult = ContentServices.updateContentMethod(dctx, context);
            } else {
                //targetOperations.add("CONTENT_CREATE");
                Map<String, Object> contentContext = FastMap.newInstance();
                ModelService contentModel = dispatcher.getDispatchContext().getModelService("createContent");
                contentContext.putAll(contentModel.makeValid(content, "IN"));
                contentContext.put("userLogin", userLogin);
                contentContext.put("displayFailCond", bDisplayFailCond);
                contentContext.put("skipPermissionCheck", context.get("skipPermissionCheck"));
                Debug.logInfo("In persistContentAndAssoc calling createContent with content: " + contentContext, module);
                Map<String, Object> thisResult = dispatcher.runSync("createContent", contentContext);
                if (ServiceUtil.isError(thisResult) || ServiceUtil.isFailure(thisResult)) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentContentCreatingError", UtilMisc.toMap("serviceName", "persistContentAndAssoc"), locale), null, null, thisResult);
                }
                //Map thisResult = ContentServices.createContentMethod(dctx, context);

                contentId = (String) thisResult.get("contentId");
            }
            results.put("contentId", contentId);
            context.put("contentId", contentId);
            context.put("caContentIdTo", contentId);

            // Add ContentPurposes if this is a create operation
            if (contentId != null && !contentExists) {
                try {
                    if (contentPurposeList != null) {
                        Set<String> contentPurposeSet = UtilMisc.makeSetWritable(contentPurposeList);
                        for (String contentPurposeTypeId : contentPurposeSet) {
                            GenericValue contentPurpose = delegator.makeValue("ContentPurpose", UtilMisc.toMap("contentId", contentId, "contentPurposeTypeId", contentPurposeTypeId));
                            contentPurpose.create();
                        }
                    }
                } catch (GenericEntityException e) {
                    return ServiceUtil.returnError(e.toString());
                }
            }

        } else if (UtilValidate.isNotEmpty(dataResourceTypeId) && UtilValidate.isNotEmpty(contentId)) {
            // If dataResource was not previously existing, then update the associated content with its id
            if (UtilValidate.isNotEmpty(dataResourceId) && !dataResourceExists) {
                Map<String, Object> map = FastMap.newInstance();
                map.put("userLogin", userLogin);
                map.put("dataResourceId", dataResourceId);
                map.put("contentId", contentId);
                if (Debug.infoOn()) Debug.logInfo("in persist... context:" + context, module);
                Map<String, Object> r = ContentServices.updateContentMethod(dctx, map);
                boolean isError = ModelService.RESPOND_ERROR.equals(r.get(ModelService.RESPONSE_MESSAGE));
                if (isError)
                    return ServiceUtil.returnError((String)r.get(ModelService.ERROR_MESSAGE));
            }
        }

        // If parentContentIdTo or parentContentIdFrom exists, create association with newly created content
        if (Debug.infoOn()) {
            Debug.logInfo("CREATING contentASSOC contentAssocTypeId:" + contentAssocTypeId, null);
        }
        // create content assoc if the key values are present....
        Debug.logInfo("contentAssoc: " + contentAssoc.toString(), null);
        if (UtilValidate.isNotEmpty(contentAssocTypeId) && contentAssoc.get("contentId") != null && contentAssoc.get("contentIdTo") != null) {
            if (Debug.infoOn())
                Debug.logInfo("in persistContentAndAssoc, deactivateExisting:" + deactivateExisting, null);
            Map<String, Object> contentAssocContext = FastMap.newInstance();
            contentAssocContext.put("userLogin", userLogin);
            contentAssocContext.put("displayFailCond", bDisplayFailCond);
            contentAssocContext.put("skipPermissionCheck", context.get("skipPermissionCheck"));
            Map<String, Object> thisResult = null;
            try {
                GenericValue contentAssocExisting = EntityQuery.use(delegator).from("ContentAssoc").where(contentAssoc.getPrimaryKey()).queryOne();
                if (contentAssocExisting == null) {
                    ModelService contentAssocModel = dispatcher.getDispatchContext().getModelService("createContentAssoc");
                    Map<String, Object> ctx = contentAssocModel.makeValid(contentAssoc, "IN");
                    contentAssocContext.putAll(ctx);
                    thisResult = dispatcher.runSync("createContentAssoc", contentAssocContext);
                    String errMsg = ServiceUtil.getErrorMessage(thisResult);
                    if (ServiceUtil.isError(thisResult) || ServiceUtil.isFailure(thisResult) || UtilValidate.isNotEmpty(errMsg)) {
                        return ServiceUtil.returnError(errMsg);
                    }
                    // results.put("contentIdTo",
                    // thisResult.get("contentIdTo"));
                    // results.put("contentIdFrom",
                    // thisResult.get("contentIdFrom"));
                    // results.put("contentId",
                    // thisResult.get("contentIdFrom"));
                    // results.put("contentAssocTypeId",
                    // thisResult.get("contentAssocTypeId"));
                    // results.put("fromDate", thisResult.get("fromDate"));
                    // results.put("sequenceNum",
                    // thisResult.get("sequenceNum"));

                    results.put("caContentIdTo", thisResult.get("contentIdTo"));
                    results.put("caContentId", thisResult.get("contentIdFrom"));
                    results.put("caContentAssocTypeId", thisResult.get("contentAssocTypeId"));
                    results.put("caFromDate", thisResult.get("fromDate"));
                    results.put("caSequenceNum", thisResult.get("sequenceNum"));
                } else {
                    if (deactivateExisting) {
                        contentAssocExisting.put("thruDate", UtilDateTime.nowTimestamp());
                    }
                    ModelService contentAssocModel = dispatcher.getDispatchContext().getModelService("updateContentAssoc");
                    Map<String, Object> ctx = contentAssocModel.makeValid(contentAssoc, "IN");
                    contentAssocContext.putAll(ctx);
                    thisResult = dispatcher.runSync("updateContentAssoc", contentAssocContext);
                    String errMsg = ServiceUtil.getErrorMessage(thisResult);
                    if (ServiceUtil.isError(thisResult) || ServiceUtil.isFailure(thisResult) || UtilValidate.isNotEmpty(errMsg)) {
                        return ServiceUtil.returnError(errMsg);
                    }
                }
            } catch (GenericEntityException e) {
                throw new GenericServiceException(e.toString());
            } catch (Exception e2) {
                throw new GenericServiceException(e2.toString());
            }
            String errMsg = ServiceUtil.getErrorMessage(thisResult);
            if (UtilValidate.isNotEmpty(errMsg)) {
                return ServiceUtil.returnError(errMsg);
            }
        }
        context.remove("skipPermissionCheck");
        context.put("contentId", origContentId);
        context.put("dataResourceId", origDataResourceId);
        context.remove("dataResource");
        Debug.logInfo("results:" + results, module);
        return results;
    }

    /**
    Service for update publish sites with a ContentRole that will tie them to the passed
    in party.
   */
    public static Map<String, Object> updateSiteRoles(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        GenericValue userLogin = (GenericValue)context.get("userLogin");
        //String userLoginPartyId = userLogin.getString("partyId");
      Map<String, Object> results = FastMap.newInstance();
      // siteContentId will equal "ADMIN_MASTER", "AGINC_MASTER", etc.
      // Remember that this service is called in the "multi" mode,
      // with a new siteContentId each time.
      // siteContentId could also have been name deptContentId, since this same
      // service is used for updating department roles, too.
      String siteContentId = (String)context.get("contentId");
      String partyId = (String)context.get("partyId");

      if (UtilValidate.isEmpty(siteContentId) || UtilValidate.isEmpty(partyId))
          return results;

      //Debug.logInfo("updateSiteRoles, context(0):" + context, module);

      List<GenericValue> siteRoles = null;
      try {
          siteRoles = EntityQuery.use(delegator).from("RoleType").where("parentTypeId", "BLOG").cache().queryList();
      } catch (GenericEntityException e) {
          return ServiceUtil.returnError(e.toString());
      }

      for (GenericValue roleType : siteRoles) {
          Map<String, Object> serviceContext = FastMap.newInstance();
          serviceContext.put("partyId", partyId);
          serviceContext.put("contentId", siteContentId);
          serviceContext.put("userLogin", userLogin);
          Debug.logInfo("updateSiteRoles, serviceContext(0):" + serviceContext, module);
          String siteRole = (String)roleType.get("roleTypeId"); // BLOG_EDITOR, BLOG_ADMIN, etc.
          String cappedSiteRole = ModelUtil.dbNameToVarName(siteRole);
          if (Debug.infoOn()) {
              Debug.logInfo("updateSiteRoles, cappediteRole(1):" + cappedSiteRole, module);
          }
          String siteRoleVal = (String)context.get(cappedSiteRole);
          if (Debug.infoOn()) {
              Debug.logInfo("updateSiteRoles, siteRoleVal(1):" + siteRoleVal, module);
              Debug.logInfo("updateSiteRoles, context(1):" + context, module);
          }
          Object fromDate = context.get(cappedSiteRole + "FromDate");
          if (Debug.infoOn()) {
              Debug.logInfo("updateSiteRoles, fromDate(1):" + fromDate, module);
          }
          serviceContext.put("roleTypeId", siteRole);
          if (siteRoleVal != null && siteRoleVal.equalsIgnoreCase("Y")) {
              // for now, will assume that any error is due to duplicates - ignore
              //return ServiceUtil.returnError(e.toString());
              if (fromDate == null) {
                  try {
                      Map<String, Object> newContext = FastMap.newInstance();
                      newContext.put("contentId", serviceContext.get("contentId"));
                      newContext.put("partyId", serviceContext.get("partyId"));
                      newContext.put("roleTypeId", serviceContext.get("roleTypeId"));
                      newContext.put("userLogin", userLogin);
                      Map<String, Object> permResults = dispatcher.runSync("deactivateAllContentRoles", newContext);
                      serviceContext.put("fromDate", UtilDateTime.nowTimestamp());
                      if (Debug.infoOn()) Debug.logInfo("updateSiteRoles, serviceContext(1):" + serviceContext, module);
                      permResults = dispatcher.runSync("createContentRole", serviceContext);
                      String errMsg = ServiceUtil.getErrorMessage(permResults);
                      if (UtilValidate.isNotEmpty(errMsg)) {
                          return ServiceUtil.returnError(errMsg);
                      } 
                      //addRoleToUser(delegator, dispatcher, serviceContext);
                  } catch (GenericServiceException e) {
                      Debug.logError(e, e.toString(), module);
                      return ServiceUtil.returnError(e.toString());
                  } catch (Exception e2) {
                      Debug.logError(e2, e2.toString(), module);
                      return ServiceUtil.returnError(e2.toString());
                  }
              }
          } else {
              if (fromDate != null) {
                  // for now, will assume that any error is due to non-existence - ignore
                  //return ServiceUtil.returnError(e.toString());
                  try {
                      Debug.logInfo("updateSiteRoles, serviceContext(2):" + serviceContext, module);
                      //Timestamp thruDate = UtilDateTime.nowTimestamp();
                      //serviceContext.put("thruDate", thruDate);
                      //serviceContext.put("fromDate", fromDate);
                      Map<String, Object> newContext = FastMap.newInstance();
                      newContext.put("contentId", serviceContext.get("contentId"));
                      newContext.put("partyId", serviceContext.get("partyId"));
                      newContext.put("roleTypeId", serviceContext.get("roleTypeId"));
                      newContext.put("userLogin", userLogin);
                      Map<String, Object> permResults = dispatcher.runSync("deactivateAllContentRoles", newContext);
                      String errMsg = ServiceUtil.getErrorMessage(permResults);
                      if (UtilValidate.isNotEmpty(errMsg))
                        return ServiceUtil.returnError(errMsg);
                  } catch (GenericServiceException e) {
                      Debug.logError(e, e.toString(), module);
                      return ServiceUtil.returnError(e.toString());
                  } catch (Exception e2) {
                      Debug.logError(e2, e2.toString(), module);
                      return ServiceUtil.returnError(e2.toString());
                  }
              }
          }
      }
      return results;
  }

    public static Map<String, Object> persistDataResourceAndData(DispatchContext dctx, Map<String, ? extends Object> context) {
      //Delegator delegator = dctx.getDelegator();
      LocalDispatcher dispatcher = dctx.getDispatcher();
      //String contentId = (String)context.get("contentId");
      Locale locale = (Locale) context.get("locale");
      Map<String, Object> result = FastMap.newInstance();
      try {
          //GenericValue content = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
          ModelService checkPermModel = dispatcher.getDispatchContext().getModelService("checkContentPermission");
          Map<String, Object> ctx = checkPermModel.makeValid(context, "IN");
          Map<String, Object> thisResult = dispatcher.runSync("checkContentPermission", ctx);
          String permissionStatus = (String)thisResult.get("permissionStatus");
          if (UtilValidate.isNotEmpty(permissionStatus) && permissionStatus.equalsIgnoreCase("granted")) {
              result = persistDataResourceAndDataMethod(dctx, context);
          }
          else {
              return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentContentNoAccessToUploadImage", locale));
          }
      } catch (GenericServiceException e) {
          Debug.logError(e, e.toString(), module);
          return ServiceUtil.returnError(e.toString());
      } catch (GenericEntityException e) {
          Debug.logError(e, e.toString(), module);
          return ServiceUtil.returnError(e.toString());
      } catch (Exception e) {
          Debug.logError(e, e.toString(), module);
          return ServiceUtil.returnError(e.toString());
      }
      String errorMsg = ServiceUtil.getErrorMessage(result);
      if (UtilValidate.isNotEmpty(errorMsg)) {
          return ServiceUtil.returnError(errorMsg);
      }
      return result;
    }

    public static Map<String, Object> persistDataResourceAndDataMethod(DispatchContext dctx, Map<String, ? extends Object> rcontext) throws GenericServiceException, GenericEntityException, Exception {
      Delegator delegator = dctx.getDelegator();
      LocalDispatcher dispatcher = dctx.getDispatcher();
      Map<String, Object> context = UtilMisc.makeMapWritable(rcontext);
      Map<String, Object> result = FastMap.newInstance();
      Map<String, Object> newDrContext = FastMap.newInstance();
      GenericValue dataResource = delegator.makeValue("DataResource");
      dataResource.setPKFields(context);
      dataResource.setNonPKFields(context);
      dataResource.setAllFields(context, false, "dr", null);
      context.putAll(dataResource);

      GenericValue electronicText = delegator.makeValue("ElectronicText");
      electronicText.setPKFields(context);
      electronicText.setNonPKFields(context);
      String textData = (String)electronicText.get("textData");


      String dataResourceId = (String)dataResource.get("dataResourceId");
      String dataResourceTypeId = (String)dataResource.get("dataResourceTypeId");
      if (Debug.infoOn()) {
          Debug.logInfo("in persist... dataResourceId(0):" + dataResourceId, null);
      }
      context.put("skipPermissionCheck", "granted"); // TODO: a temp hack because I don't want to bother with DataResource permissions at this time.
      boolean dataResourceExists = true;
      if (UtilValidate.isEmpty(dataResourceId)) {
          dataResourceExists = false;
      } else {
          try {
              GenericValue val = EntityQuery.use(delegator).from("DataResource").where("dataResourceId", dataResourceId).queryOne();
              if (val == null) {
                  dataResourceExists = false;
              }
          } catch (GenericEntityException e) {
              return ServiceUtil.returnError(e.toString());
          }
      }
      GenericValue userLogin = (GenericValue) context.get("userLogin");
      //String userLoginId = (String)userLogin.get("userLoginId");
      ModelService dataResourceModel = dispatcher.getDispatchContext().getModelService("updateDataResource");
      Map<String, Object> ctx = dataResourceModel.makeValid(dataResource, "IN");
      newDrContext.putAll(ctx);
      newDrContext.put("userLogin", userLogin);
      newDrContext.put("skipPermissionCheck", context.get("skipPermissionCheck"));
      ByteBuffer imageDataBytes = (ByteBuffer) context.get("imageData");
      String mimeTypeId = (String) newDrContext.get("mimeTypeId");
      if (imageDataBytes != null && (mimeTypeId == null || (mimeTypeId.indexOf("image") >= 0) || (mimeTypeId.indexOf("application") >= 0))) {
          mimeTypeId = (String) context.get("_imageData_contentType");
          if (dataResourceTypeId.equals("IMAGE_OBJECT")) {
              String fileName = (String) context.get("_imageData_fileName");
              newDrContext.put("objectInfo", fileName);
          }
          newDrContext.put("mimeTypeId", mimeTypeId);
      }

      if (!dataResourceExists) { // Create
          Map<String, Object> thisResult = dispatcher.runSync("createDataResource", newDrContext);
          String errorMsg = ServiceUtil.getErrorMessage(thisResult);
          if (UtilValidate.isNotEmpty(errorMsg)) {
              throw(new Exception(errorMsg));
          }
          dataResourceId = (String)thisResult.get("dataResourceId");
          if (Debug.infoOn()) {
              Debug.logInfo("in persist... dataResourceId(0):" + dataResourceId, null);
          }
          dataResource = (GenericValue)thisResult.get("dataResource");
          Map<String, Object> fileContext = FastMap.newInstance();
          fileContext.put("userLogin", userLogin);
          if (dataResourceTypeId.equals("IMAGE_OBJECT")) {
              if (imageDataBytes != null) {
                  fileContext.put("dataResourceId", dataResourceId);
                  fileContext.put("imageData", imageDataBytes);
                  thisResult = dispatcher.runSync("createImage", fileContext);
                  errorMsg = ServiceUtil.getErrorMessage(thisResult);
                  if (UtilValidate.isNotEmpty(errorMsg)) {
                      return ServiceUtil.returnError(errorMsg);
                  }
              }
          } else if (dataResourceTypeId.equals("SHORT_TEXT")) {
          } else if (dataResourceTypeId.startsWith("SURVEY")) {
          } else {
              // assume ELECTRONIC_TEXT
              if (UtilValidate.isNotEmpty(textData)) {
                  fileContext.put("dataResourceId", dataResourceId);
                  fileContext.put("textData", textData);
                  thisResult = dispatcher.runSync("createElectronicText", fileContext);
                  errorMsg = ServiceUtil.getErrorMessage(thisResult);
                  if (UtilValidate.isNotEmpty(errorMsg)) {
                      return ServiceUtil.returnError(errorMsg);
                  }
              }
          }
      } else { // Update
          Map<String, Object> thisResult = dispatcher.runSync("updateDataResource", newDrContext);
          String errorMsg = ServiceUtil.getErrorMessage(thisResult);
          if (UtilValidate.isNotEmpty(errorMsg)) {
              return ServiceUtil.returnError(errorMsg);
          }
          Map<String, Object> fileContext = FastMap.newInstance();
          fileContext.put("userLogin", userLogin);
          String forceElectronicText = (String)context.get("forceElectronicText");
          if (dataResourceTypeId.equals("IMAGE_OBJECT")) {
              if (imageDataBytes != null || "true".equalsIgnoreCase(forceElectronicText)) {
                  fileContext.put("dataResourceId", dataResourceId);
                  fileContext.put("imageData", imageDataBytes);
                  thisResult = dispatcher.runSync("updateImage", fileContext);
                  errorMsg = ServiceUtil.getErrorMessage(thisResult);
                  if (UtilValidate.isNotEmpty(errorMsg)) {
                      return ServiceUtil.returnError(errorMsg);
                  }
              }
          } else if (dataResourceTypeId.equals("SHORT_TEXT")) {
          } else if (dataResourceTypeId.startsWith("SURVEY")) {
          } else {
              if (UtilValidate.isNotEmpty(textData) || "true".equalsIgnoreCase(forceElectronicText)) {
                  fileContext.put("dataResourceId", dataResourceId);
                  fileContext.put("textData", textData);
                  thisResult = dispatcher.runSync("updateElectronicText", fileContext);
                  errorMsg = ServiceUtil.getErrorMessage(thisResult);
                  if (UtilValidate.isNotEmpty(errorMsg)) {
                      return ServiceUtil.returnError(errorMsg);
                  }
              }
          }
      }
      if (dataResourceTypeId.indexOf("_FILE") >=0) {
          Map<String, Object> uploadImage = FastMap.newInstance();
          uploadImage.put("userLogin", userLogin);
          uploadImage.put("dataResourceId", dataResourceId);
          uploadImage.put("dataResourceTypeId", dataResourceTypeId);
          uploadImage.put("rootDir", context.get("objectInfo"));
          uploadImage.put("uploadedFile", imageDataBytes);
          uploadImage.put("_uploadedFile_fileName", (String) context.get("_imageData_fileName"));
          uploadImage.put("_uploadedFile_contentType", (String) context.get("_imageData_contentType"));
          dispatcher.runSync("attachUploadToDataResource", uploadImage);
      }
      result.put("dataResourceId", dataResourceId);
      result.put("drDataResourceId", dataResourceId);
      context.put("dataResourceId", dataResourceId);
      return result;
    }

    public static void addRoleToUser(Delegator delegator, LocalDispatcher dispatcher, Map<String, Object> serviceContext) throws GenericServiceException, GenericEntityException {
        List<GenericValue> userLoginList = EntityQuery.use(delegator).from("UserLogin").where("partyId", serviceContext.get("partyId")).queryList();
        for (GenericValue partyUserLogin : userLoginList) {
            String partyUserLoginId = partyUserLogin.getString("userLoginId");
            serviceContext.put("contentId", partyUserLoginId); // author contentId
            dispatcher.runSync("createContentRole", serviceContext);
        }
    }

    public static Map<String, Object> updateSiteRolesDyn(DispatchContext dctx, Map<String, ? extends Object> context) {
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Delegator delegator = dctx.getDelegator();
        Map<String, Object> results = FastMap.newInstance();
        Map<String, Object> serviceContext = FastMap.newInstance();
        // siteContentId will equal "ADMIN_MASTER", "AGINC_MASTER", etc.
        // Remember that this service is called in the "multi" mode,
        // with a new siteContentId each time.
        // siteContentId could also have been name deptContentId, since this same
        // service is used for updating department roles, too.
        String siteContentId = (String)context.get("contentId");
        String partyId = (String)context.get("partyId");
        serviceContext.put("partyId", partyId);
        serviceContext.put("contentId", siteContentId);
        //Debug.logInfo("updateSiteRoles, serviceContext(0):" + serviceContext, module);
        //Debug.logInfo("updateSiteRoles, context(0):" + context, module);

        List<GenericValue> siteRoles = null;
        try {
            siteRoles = EntityQuery.use(delegator).from("RoleType").where("parentTypeId", "BLOG").cache().queryList();
        } catch (GenericEntityException e) {
          return ServiceUtil.returnError(e.toString());
        }
        for (GenericValue roleType : siteRoles) {
            String siteRole = (String)roleType.get("roleTypeId"); // BLOG_EDITOR, BLOG_ADMIN, etc.
            String cappedSiteRole = ModelUtil.dbNameToVarName(siteRole);
            //if (Debug.infoOn()) Debug.logInfo("updateSiteRoles, cappediteRole(1):" + cappedSiteRole, module);

            String siteRoleVal = (String)context.get(cappedSiteRole);
            Object fromDate = context.get(cappedSiteRole + "FromDate");
            serviceContext.put("roleTypeId", siteRole);
            if (siteRoleVal != null && siteRoleVal.equalsIgnoreCase("Y")) {
                // for now, will assume that any error is due to duplicates - ignore
                //return ServiceUtil.returnError(e.toString());
                if (fromDate == null) {
                    try {
                        serviceContext.put("fromDate", UtilDateTime.nowTimestamp());
                        if (Debug.infoOn()) {
                            Debug.logInfo("updateSiteRoles, serviceContext(1):" + serviceContext, module);
                        }
                        addRoleToUser(delegator, dispatcher, serviceContext);
                        dispatcher.runSync("createContentRole", serviceContext);
                    } catch (GenericServiceException e) {
                        Debug.logError(e, e.toString(), module);
                    } catch (Exception e2) {
                        Debug.logError(e2, e2.toString(), module);
                    }
                }
            } else {
                if (fromDate != null) {
                    // for now, will assume that any error is due to non-existence - ignore
                    //return ServiceUtil.returnError(e.toString());
                    try {
                        Debug.logInfo("updateSiteRoles, serviceContext(2):" + serviceContext, module);
                        //Timestamp thruDate = UtilDateTime.nowTimestamp();
                        //serviceContext.put("thruDate", thruDate);
                        //serviceContext.put("fromDate", fromDate);
                        Map<String, Object> newContext = FastMap.newInstance();
                        newContext.put("contentId", serviceContext.get("contentId"));
                        newContext.put("partyId", serviceContext.get("partyId"));
                        newContext.put("roleTypeId", serviceContext.get("roleTypeId"));
                        dispatcher.runSync("deactivateAllContentRoles", newContext);
                    } catch (GenericServiceException e) {
                        Debug.logError(e, e.toString(), module);
                    } catch (Exception e2) {
                        Debug.logError(e2, e2.toString(), module);
                    }
                }
            }
        }
        return results;
    }

    public static Map<String, Object> updateOrRemove(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> results = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        String entityName = (String)context.get("entityName");
        String action = (String)context.get("action");
        String pkFieldCount = (String)context.get("pkFieldCount");
        Map<String, String> pkFields = FastMap.newInstance();
        int fieldCount = Integer.parseInt(pkFieldCount);
        for (int i=0; i<fieldCount; i++) {
            String fieldName = (String)context.get("fieldName" + i);
            String fieldValue = (String)context.get("fieldValue" + i);
            if (UtilValidate.isEmpty(fieldValue)) {
                // It may be the case that the last row in a form is "empty" waiting for
                // someone to enter a value, in which case we do not want to throw an
                // error, we just want to ignore it.
                return results;
            }
            pkFields.put(fieldName, fieldValue);
        }
        boolean doLink = (action != null && action.equalsIgnoreCase("Y")) ? true : false;
        if (Debug.infoOn()) {
            Debug.logInfo("in updateOrRemove, context:" + context, module);
        }
        try {
            GenericValue entityValuePK = delegator.makeValue(entityName, pkFields);
            if (Debug.infoOn()) {
                Debug.logInfo("in updateOrRemove, entityValuePK:" + entityValuePK, module);
            }
            GenericValue entityValueExisting = EntityQuery.use(delegator).from(entityName).where(entityValuePK).cache().queryOne();
            if (Debug.infoOn()) {
                Debug.logInfo("in updateOrRemove, entityValueExisting:" + entityValueExisting, module);
            }
            if (entityValueExisting == null) {
                if (doLink) {
                    entityValuePK.create();
                    if (Debug.infoOn()) {
                        Debug.logInfo("in updateOrRemove, entityValuePK: CREATED", module);
                    }
                }
            } else {
                if (!doLink) {
                    entityValueExisting.remove();
                    if (Debug.infoOn()) {
                        Debug.logInfo("in updateOrRemove, entityValueExisting: REMOVED", module);
                    }
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }
        return results;
    }

    public static Map<String, Object> resequence(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        String contentIdTo = (String)context.get("contentIdTo");
        Integer seqInc = (Integer)context.get("seqInc");
        if (seqInc == null) {
            seqInc = Integer.valueOf(100);
        }
        int seqIncrement = seqInc.intValue();
        List<String> typeList = UtilGenerics.checkList(context.get("typeList"));
        if (typeList == null) {
            typeList = FastList.newInstance();
        }
        String contentAssocTypeId = (String)context.get("contentAssocTypeId");
        if (UtilValidate.isNotEmpty(contentAssocTypeId)) {
            typeList.add(contentAssocTypeId);
        }
        if (UtilValidate.isEmpty(typeList)) {
            typeList = UtilMisc.toList("PUBLISH_LINK", "SUB_CONTENT");
        }
        EntityCondition conditionType = EntityCondition.makeCondition("contentAssocTypeId", EntityOperator.IN, typeList);
        EntityCondition conditionMain = EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition("contentIdTo", EntityOperator.EQUALS, contentIdTo), conditionType), EntityOperator.AND);
        try {
            List<GenericValue> listAll = EntityQuery.use(delegator).from("ContentAssoc")
                    .where(conditionMain)
                    .orderBy("sequenceNum", "fromDate", "createdDate")
                    .filterByDate().queryList();
            String contentId = (String)context.get("contentId");
            String dir = (String)context.get("dir");
            int seqNum = seqIncrement;
            String thisContentId = null;
            for (int i=0; i < listAll.size(); i++) {
                GenericValue contentAssoc = listAll.get(i);
                if (UtilValidate.isNotEmpty(contentId) && UtilValidate.isNotEmpty(dir)) {
                    // move targeted entry up or down
                    thisContentId = contentAssoc.getString("contentId");
                    if (contentId.equals(thisContentId)) {
                        if (dir.startsWith("up")) {
                            if (i > 0) {
                                // Swap with previous entry
                                try {
                                    GenericValue prevValue = listAll.get(i-1);
                                    Long prevSeqNum = (Long)prevValue.get("sequenceNum");
                                    prevValue.put("sequenceNum", Long.valueOf(seqNum));
                                    prevValue.store();
                                    contentAssoc.put("sequenceNum", prevSeqNum);
                                    contentAssoc.store();
                                } catch (Exception e) {
                                    return ServiceUtil.returnError(e.toString());
                                }
                            }
                        } else {
                            if (i < listAll.size()) {
                                // Swap with next entry
                                GenericValue nextValue = listAll.get(i+1);
                                nextValue.put("sequenceNum", Long.valueOf(seqNum));
                                nextValue.store();
                                seqNum += seqIncrement;
                                contentAssoc.put("sequenceNum", Long.valueOf(seqNum));
                                contentAssoc.store();
                                i++; // skip next one
                            }
                        }
                    } else {
                        contentAssoc.put("sequenceNum", Long.valueOf(seqNum));
                        contentAssoc.store();
                    }
                } else {
                    contentAssoc.put("sequenceNum", Long.valueOf(seqNum));
                    contentAssoc.store();
                }
                seqNum += seqIncrement;
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

    public static Map<String, Object> changeLeafToNode(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        String contentId = (String)context.get("contentId");
        GenericValue userLogin = (GenericValue)context.get("userLogin");
        String userLoginId = userLogin.getString("userLoginId");
        Locale locale = (Locale) context.get("locale");
        //int seqNum = 9999;
        try {
            GenericValue content = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
            if (content == null) {
                Debug.logError("content was null", module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentNoContentFound", UtilMisc.toMap("contentId", ""), locale));
            }
            String dataResourceId = content.getString("dataResourceId");
            //String contentTypeIdTo = content.getString("contentTypeId");
            /* this does not seem to be correct or needed
            if (UtilValidate.isNotEmpty(contentTypeIdTo)) {
                if (contentTypeIdTo.equals("OUTLINE_NODE")) {
                    content.put("contentTypeId", "OUTLINE_NODE");
                } else if (contentTypeIdTo.equals("PAGE_NODE")) {
                    content.put("contentTypeId", "SUBPAGE_NODE");
                } else
                    content.put("contentTypeId", "PAGE_NODE");
            }
            */

            content.set("dataResourceId", null);
            content.set("lastModifiedDate", UtilDateTime.nowTimestamp());
            content.set("lastModifiedByUserLogin", userLoginId);
            content.store();

            if (UtilValidate.isNotEmpty(dataResourceId)) {
                // add previous DataResource as part of new subcontent
                GenericValue contentClone = (GenericValue)content.clone();
                contentClone.set("dataResourceId", dataResourceId);
                content.set("lastModifiedDate", UtilDateTime.nowTimestamp());
                content.set("lastModifiedByUserLogin", userLoginId);
                content.set("createdDate", UtilDateTime.nowTimestamp());
                content.set("createdByUserLogin", userLoginId);

                contentClone.set("contentId", null);
                ModelService modelService = dctx.getModelService("persistContentAndAssoc");
                Map<String, Object> serviceIn = modelService.makeValid(contentClone, "IN");
                serviceIn.put("userLogin", userLogin);
                serviceIn.put("contentIdTo", contentId);
                serviceIn.put("contentAssocTypeId", "SUB_CONTENT");
                serviceIn.put("sequenceNum", Long.valueOf(50));
                try {
                    dispatcher.runSync("persistContentAndAssoc", serviceIn);
                } catch (ServiceAuthException e) {
                    return ServiceUtil.returnError(e.toString());
                }

                List<String> typeList = UtilMisc.toList("SUB_CONTENT");
                ContentManagementWorker.updateStatsTopDown(delegator, contentId, typeList);
            }

        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

    public static Map<String, Object> updateLeafCount(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        List<String> typeList = UtilGenerics.checkList(context.get("typeList"));
        if (typeList == null) {
            typeList = UtilMisc.toList("PUBLISH_LINK", "SUB_CONTENT");
        }
        String startContentId = (String)context.get("contentId");
        try {
            int leafCount = ContentManagementWorker.updateStatsTopDown(delegator, startContentId, typeList);
            result.put("leafCount", Integer.valueOf(leafCount));
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

/*
    public static Map<String, Object> updateLeafChange(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{

        Map result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        List typeList = (List)context.get("typeList");
        if (typeList == null)
            typeList = UtilMisc.toList("PUBLISH_LINK", "SUB_CONTENT");
        String contentId = (String)context.get("contentId");

        try {
            GenericValue thisContent = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
            if (thisContent == null)
                throw new RuntimeException("No entity found for id=" + contentId);

            String thisContentId = thisContent.getString("contentId");
            Long leafCount = (Long)thisContent.get("nodeLeafCount");
            int subLeafCount = (leafCount == null) ? 1 : leafCount.intValue();
            String mode = (String)context.get("mode");
            if (mode != null && mode.equalsIgnoreCase("remove")) {
                subLeafCount *= -1;
            } else {
                // TODO: ??? what is this supposed to do:
                //subLeafCount = subLeafCount;
            }

           EntityCondition conditionType = EntityCondition.makeCondition("contentAssocTypeId", EntityOperator.IN, typeList);
           EntityCondition conditionMain = EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition("contentId", EntityOperator.EQUALS, thisContentId), conditionType), EntityOperator.AND);
            List listFiltered = EntityQuery.use(delegator).from("ContentAssoc").where(mainCondition).cache().filterByDate().queryList();
            Iterator iter = listFiltered.iterator();
            while (iter.hasNext()) {
                GenericValue contentAssoc = (GenericValue)iter.next();
                String subContentId = contentAssoc.getString("contentId");
                GenericValue contentTo = EntityQuery.use(delegator).from("Content").where("contentId", subContentId).cache().queryOne();
                Integer childBranchCount = (Integer)contentTo.get("childBranchCount");
                int branchCount = (childBranchCount == null) ? 1 : childBranchCount.intValue();
                if (mode != null && mode.equalsIgnoreCase("remove"))
                    branchCount += -1;
                else
                    branchCount += 1;
                // For the level just above only, update the branch count
                contentTo.put("childBranchCount", Integer.valueOf(branchCount));

                // Start the updating of leaf counts above
                ContentManagementWorker.updateStatsBottomUp(delegator, subContentId, typeList, subLeafCount);
            }


        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }
    */

    /**
     * This service changes the contentTypeId of the current content and its children depending on the pageMode.
     * if pageMode == "outline" then if the contentTypeId of children is not "OUTLINE_NODE" or "PAGE_NODE"
     * (it could be DOCUMENT or SUBPAGE_NODE) then it will get changed to PAGE_NODE.`
     * if pageMode == "page" then if the contentTypeId of children is not "PAGE_NODE" or "SUBPAGE_NODE"
     * (it could be DOCUMENT or OUTLINE_NODE) then it will get changed to SUBPAGE_NODE.`
     */
    public static Map<String, Object> updatePageType(DispatchContext dctx, Map<String, ? extends Object> rcontext) throws GenericServiceException{
        Delegator delegator = dctx.getDelegator();
        Map<String, Object> context = UtilMisc.makeMapWritable(rcontext);
        Map<String, Object> results = FastMap.newInstance();
        Locale locale = (Locale) context.get("locale");
        Set<String> visitedSet = UtilGenerics.checkSet(context.get("visitedSet"));
        if (visitedSet == null) {
            visitedSet = FastSet.newInstance();
            context.put("visitedSet", visitedSet);
        }
        String pageMode = (String)context.get("pageMode");
        String contentId = (String)context.get("contentId");
        visitedSet.add(contentId);
        String contentTypeId = "PAGE_NODE";
        if (pageMode != null && pageMode.toLowerCase().indexOf("outline") >= 0)
            contentTypeId = "OUTLINE_NODE";
        GenericValue thisContent = null;
        try {
            thisContent = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
            if (thisContent == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentNoContentFound", UtilMisc.toMap("contentId", contentId), locale));
            }
            thisContent.set("contentTypeId", contentTypeId);
            thisContent.store();
            List<GenericValue> kids = ContentWorker.getAssociatedContent(thisContent, "from", UtilMisc.toList("SUB_CONTENT"), null, null, null);
            for (GenericValue kidContent : kids) {
                if (contentTypeId.equals("OUTLINE_NODE")) {
                    updateOutlineNodeChildren(kidContent, false, context);
                } else {
                    updatePageNodeChildren(kidContent, context);
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }

        return results;
    }

    public static Map<String, Object> resetToOutlineMode(DispatchContext dctx, Map<String, ? extends Object> rcontext) throws GenericServiceException{
        Delegator delegator = dctx.getDelegator();
        Map<String, Object> context = UtilMisc.makeMapWritable(rcontext);
        Map<String, Object> results = FastMap.newInstance();
        Locale locale = (Locale) context.get("locale");
        Set<String> visitedSet = UtilGenerics.checkSet(context.get("visitedSet"));
        if (visitedSet == null) {
            visitedSet = FastSet.newInstance();
            context.put("visitedSet", visitedSet);
        }
        String contentId = (String)context.get("contentId");
        String pageMode = (String)context.get("pageMode");
        String contentTypeId = "OUTLINE_NODE";
        if (pageMode != null && pageMode.toLowerCase().indexOf("page") >= 0) {
            contentTypeId = "PAGE_NODE";
        }
        GenericValue thisContent = null;
        try {
            thisContent = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
            if (thisContent == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                        "ContentNoContentFound", UtilMisc.toMap("contentId", contentId), locale));
            }
            thisContent.set("contentTypeId", "OUTLINE_NODE");
            thisContent.store();
            List<GenericValue> kids = ContentWorker.getAssociatedContent(thisContent, "from", UtilMisc.toList("SUB_CONTENT"), null, null, null);
            for (GenericValue kidContent : kids) {
                if (contentTypeId.equals("OUTLINE_NODE")) {
                    updateOutlineNodeChildren(kidContent, true, context);
                } else {
                    kidContent.put("contentTypeId", "PAGE_NODE");
                    kidContent.store();
                    List<GenericValue> kids2 = ContentWorker.getAssociatedContent(kidContent, "from", UtilMisc.toList("SUB_CONTENT"), null, null, null);
                    for (GenericValue kidContent2 : kids2) {
                        updatePageNodeChildren(kidContent2, context);
                    }
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }
        return results;
    }

    public static Map<String, Object> clearContentAssocViewCache(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> results = FastMap.newInstance();
        Cache<?, ?> utilCache = UtilCache.findCache("entitycache.entity-list.default.ContentAssocViewFrom");

        if (utilCache != null) {
            utilCache.clear();
        }

        utilCache = UtilCache.findCache("entitycache.entity-list.default.ContentAssocViewTo");
        if (utilCache != null) {
            utilCache.clear();
        }

        return results;
    }

    public static Map<String, Object> clearContentAssocDataResourceViewCache(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> results = FastMap.newInstance();

        Cache<?, ?> utilCache = UtilCache.findCache("entitycache.entity-list.default.ContentAssocViewDataResourceFrom");
        if (utilCache != null) {
            utilCache.clear();
        }

        utilCache = UtilCache.findCache("entitycache.entity-list.default.ContentAssocViewDataResourceTo");
        if (utilCache != null) {
            utilCache.clear();
        }

        return results;
    }

    public static void updatePageNodeChildren(GenericValue content, Map<String, Object> context) throws GenericEntityException {
        String contentId = content.getString("contentId");
        Set<String> visitedSet = UtilGenerics.checkSet(context.get("visitedSet"));
        if (visitedSet == null) {
            visitedSet = FastSet.newInstance();
            context.put("visitedSet", visitedSet);
        } else {
            if (visitedSet.contains(contentId)) {
                Debug.logWarning("visitedSet already contains:" + contentId, module);
                return;
            } else {
                visitedSet.add(contentId);
            }
        }
        // String contentTypeId = content.getString("contentTypeId");
        String newContentTypeId = "SUBPAGE_NODE";
//        if (contentTypeId == null || contentTypeId.equals("DOCUMENT")) {
//            newContentTypeId = "SUBPAGE_NODE";
//        } else if (contentTypeId.equals("OUTLINE_NODE")) {
//            newContentTypeId = "PAGE_NODE";
//        }

        content.put("contentTypeId", newContentTypeId);
        content.store();

        //if (contentTypeId == null || contentTypeId.equals("OUTLINE_DOCUMENT") || contentTypeId.equals("DOCUMENT")) {
        List<GenericValue> kids = ContentWorker.getAssociatedContent(content, "from", UtilMisc.toList("SUB_CONTENT"), null, null, null);
        for (GenericValue kidContent : kids) {
            updatePageNodeChildren(kidContent, context);
        }
        //}
    }

    public static void updateOutlineNodeChildren(GenericValue content, boolean forceOutline, Map<String, Object> context) throws GenericEntityException {
        String contentId = content.getString("contentId");
        Set<String> visitedSet = UtilGenerics.checkSet(context.get("visitedSet"));
        if (visitedSet == null) {
            visitedSet = FastSet.newInstance();
            context.put("visitedSet", visitedSet);
        } else {
            if (visitedSet.contains(contentId)) {
                Debug.logWarning("visitedSet already contains:" + contentId, module);
                return;
            } else {
                visitedSet.add(contentId);
            }
        }
        String contentTypeId = content.getString("contentTypeId");
        String newContentTypeId = contentTypeId;
        String dataResourceId = content.getString("dataResourceId");
        Long branchCount = (Long)content.get("childBranchCount");
        if (forceOutline) {
            newContentTypeId = "OUTLINE_NODE";
        } else if (contentTypeId == null || contentTypeId.equals("DOCUMENT")) {
            if (UtilValidate.isEmpty(dataResourceId) || (branchCount != null && branchCount.intValue() > 0)) {
                newContentTypeId = "OUTLINE_NODE";
            } else {
                newContentTypeId = "PAGE_NODE";
            }
        } else if (contentTypeId.equals("SUBPAGE_NODE")) {
            newContentTypeId = "PAGE_NODE";
        }

        content.put("contentTypeId", newContentTypeId);
        content.store();

        if (contentTypeId == null || contentTypeId.equals("DOCUMENT") || contentTypeId.equals("OUTLINE_NODE")) {
        //if (contentTypeId == null || contentTypeId.equals("DOCUMENT")) {
            List<GenericValue> kids = ContentWorker.getAssociatedContent(content, "from", UtilMisc.toList("SUB_CONTENT"), null, null, null);
            for (GenericValue kidContent : kids) {
                updateOutlineNodeChildren(kidContent, forceOutline, context);
            }
        }
    }

    public static Map<String, Object> findSubNodes(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> results = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        String contentIdTo = (String)context.get("contentId");
        try {
             List<GenericValue> lst = EntityQuery.use(delegator).from("ContentAssocDataResourceViewFrom")
                     .where("caContentIdTo", contentIdTo,
                             "caContentAssocTypeId", "SUB_CONTENT",
                             "caThruDate", null)
                     .orderBy("caSequenceNum", "caFromDate", "createdDate")
                     .queryList();
             results.put("_LIST_", lst);
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            return ServiceUtil.returnError(e.toString());
        }
        return results;
    }

    public static String updateTypeAndFile(GenericValue dataResource, Map<String, Object> context) {
        String retVal = null;
        String mimeTypeId = (String) context.get("_imageData_contentType");
        String fileName = (String) context.get("_imageData_fileName");
        try {
            if (UtilValidate.isNotEmpty(fileName))
                dataResource.set("objectInfo", fileName);
            if (UtilValidate.isNotEmpty(mimeTypeId))
                dataResource.set("mimeTypeId", mimeTypeId);
            dataResource.store();
        } catch (GenericEntityException e) {
            retVal = "Unable to update the DataResource record";
        }
        return retVal;
    }

    public static Map<String, Object> initContentChildCounts(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = FastMap.newInstance();
        Locale locale = (Locale) context.get("locale");
        GenericValue content = (GenericValue)context.get("content");
        if (content == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentNoContentFound", UtilMisc.toMap("contentId", ""), locale));
        }
        Long leafCount = (Long)content.get("childLeafCount");
        if (leafCount == null) {
            content.set("childLeafCount", Long.valueOf(0));
        }
        Long branchCount = (Long)content.get("childBranchCount");
        if (branchCount == null) {
            content.set("childBranchCount", Long.valueOf(0));
        }

        //content.store();

        return result;
    }

    public static Map<String, Object> incrementContentChildStats(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String contentId = (String)context.get("contentId");
        String contentAssocTypeId = (String)context.get("contentAssocTypeId");

        try {
            GenericValue content = EntityQuery.use(delegator).from("Content").where("contentId", contentId).cache().queryOne();
            if (content == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentNoContentFound", UtilMisc.toMap("contentId", contentId), locale));
            }
            Long leafCount = (Long)content.get("childLeafCount");
            if (leafCount == null) {
                leafCount = Long.valueOf(0);
            }
            int changeLeafCount = leafCount.intValue() + 1;
            int changeBranchCount = 1;

            ContentManagementWorker.updateStatsBottomUp(delegator, contentId, UtilMisc.toList(contentAssocTypeId), changeBranchCount, changeLeafCount);
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

    public static Map<String, Object> decrementContentChildStats(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        Locale locale = (Locale) context.get("locale");
        String contentId = (String)context.get("contentId");
        String contentAssocTypeId = (String)context.get("contentAssocTypeId");

        try {
            GenericValue content = EntityQuery.use(delegator).from("Content").where("contentId", contentId).cache().queryOne();
            if (content == null) {
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentNoContentFound", UtilMisc.toMap("contentId", contentId), locale));
            }
            Long leafCount = (Long)content.get("childLeafCount");
            if (leafCount == null) {
                leafCount = Long.valueOf(0);
            }
            int changeLeafCount = -1 * leafCount.intValue() - 1;
            int changeBranchCount = -1;

            ContentManagementWorker.updateStatsBottomUp(delegator, contentId, UtilMisc.toList(contentAssocTypeId), changeBranchCount, changeLeafCount);
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

    public static Map<String, Object> updateContentChildStats(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();

        String contentId = (String)context.get("contentId");
        String contentAssocTypeId = (String)context.get("contentAssocTypeId");
        List<String> typeList = FastList.newInstance();
        if (UtilValidate.isNotEmpty(contentAssocTypeId)) {
            typeList.add(contentAssocTypeId);
        } else {
            typeList = UtilMisc.toList("PUBLISH_LINK", "SUB_CONTENT");
        }

        try {
            ContentManagementWorker.updateStatsTopDown(delegator, contentId, typeList);
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

    public static Map<String, Object> updateContentSubscription(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Timestamp nowTimestamp = UtilDateTime.nowTimestamp();

        String partyId = (String) context.get("partyId");
        String webPubPt = (String) context.get("contentId");
        String roleTypeId = (String) context.get("useRoleTypeId");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        Integer useTime = (Integer) context.get("useTime");
        String useTimeUomId = (String) context.get("useTimeUomId");
        boolean hasExistingContentRole = false;
        GenericValue contentRole = null;
        try {
            contentRole = EntityQuery.use(delegator).from("ContentRole")
                    .where("partyId", partyId, "contentId", webPubPt, "roleTypeId", roleTypeId)
                    .orderBy("fromDate DESC")
                    .cache().filterByDate()
                    .queryFirst();
            if (contentRole != null) {
                hasExistingContentRole = true;
            }
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        }

        if (contentRole == null) {
            contentRole = delegator.makeValue("ContentRole");
            contentRole.set("contentId", webPubPt);
            contentRole.set("partyId", partyId);
            contentRole.set("roleTypeId", roleTypeId);
            contentRole.set("fromDate", nowTimestamp);
        }

        Timestamp thruDate = (Timestamp) contentRole.get("thruDate");
        if (thruDate == null) {
            // no thruDate? start with NOW
            thruDate = nowTimestamp;
        } else {
            // there is a thru date... if it is in the past, bring it up to NOW before adding on the time period
            //don't want to penalize for skipping time, in other words if they had a subscription last year for a month and buy another month, we want that second month to start now and not last year
            if (thruDate.before(nowTimestamp)) {
                thruDate = nowTimestamp;
            }
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(thruDate);
        int field = Calendar.MONTH;
        if ("TF_day".equals(useTimeUomId)) {
            field = Calendar.DAY_OF_YEAR;
        } else if ("TF_wk".equals(useTimeUomId)) {
            field = Calendar.WEEK_OF_YEAR;
        } else if ("TF_mon".equals(useTimeUomId)) {
            field = Calendar.MONTH;
        } else if ("TF_yr".equals(useTimeUomId)) {
            field = Calendar.YEAR;
        } else {
            Debug.logWarning("Don't know anything about useTimeUomId [" + useTimeUomId + "], defaulting to month", module);
        }
        calendar.add(field, useTime.intValue());
        thruDate = new Timestamp(calendar.getTimeInMillis());
        contentRole.set("thruDate", thruDate);
        try {
            if (hasExistingContentRole) {
                contentRole.store();
            } else {
                Map<String, Object> map = FastMap.newInstance();
                map.put("partyId", partyId);
                map.put("roleTypeId", roleTypeId);
                map.put("userLogin", userLogin);
                dispatcher.runSync("createPartyRole", map);
                contentRole.create();
            }
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

    public static Map<String, Object> updateContentSubscriptionByProduct(DispatchContext dctx, Map<String, ? extends Object> rcontext) throws GenericServiceException{
        Map<String, Object> context = UtilMisc.makeMapWritable(rcontext);
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        String productId = (String) context.get("productId");
        Integer qty = (Integer) context.get("quantity");
        if (qty == null) {
            qty = Integer.valueOf(1);
        }

        Timestamp orderCreatedDate = (Timestamp) context.get("orderCreatedDate");
        if (orderCreatedDate == null) {
            orderCreatedDate = UtilDateTime.nowTimestamp();
        }
        GenericValue productContent = null;
           try {
            List<GenericValue> lst = EntityQuery.use(delegator).from("ProductContent")
                    .where("productId", productId, "productContentTypeId", "ONLINE_ACCESS")
                    .orderBy("purchaseFromDate", "purchaseThruDate")
                    .filterByDate("purchaseFromDate", "purchaseThruDate")
                    .cache().queryList();
            List<GenericValue> listThrusOnly = EntityUtil.filterOutByCondition(lst, EntityCondition.makeCondition("purchaseThruDate", EntityOperator.EQUALS, null));
            if (listThrusOnly.size() > 0) {
                productContent = listThrusOnly.get(0);
            } else if (lst.size() > 0) {
                productContent = lst.get(0);
            }
        } catch (GenericEntityException e) {
            Debug.logError(e.toString(), module);
            return ServiceUtil.returnError(e.toString());
        }
        if (productContent == null) {
            String msg = "No ProductContent found for productId:" + productId;
            Debug.logError(msg, module);
            return ServiceUtil.returnError(msg);
        }
        Long useTime = (Long) productContent.get("useTime");
        Integer newUseTime = null;
        if (UtilValidate.isNotEmpty(useTime)) {
            newUseTime = Integer.valueOf(useTime.intValue() * qty.intValue());
        }
        context.put("useTime", newUseTime);
        context.put("useTimeUomId", productContent.get("useTimeUomId"));
        context.put("useRoleTypeId", productContent.get("useRoleTypeId"));
        context.put("contentId", productContent.get("contentId"));
        ModelService subscriptionModel = dispatcher.getDispatchContext().getModelService("updateContentSubscription");
        Map<String, Object> ctx = subscriptionModel.makeValid(context, "IN");
        result = dispatcher.runSync("updateContentSubscription", ctx);
        return result;
    }

    public static Map<String, Object> updateContentSubscriptionByOrder(DispatchContext dctx, Map<String, ? extends Object> rcontext) throws GenericServiceException{
        Map<String, Object> context = UtilMisc.makeMapWritable(rcontext);
        Map<String, Object> result = FastMap.newInstance();
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        String orderId = (String) context.get("orderId");

        Debug.logInfo("In updateContentSubscriptionByOrder service with orderId: " + orderId, module);

        GenericValue orderHeader = null;
        try {
            GenericValue orderRole = EntityQuery.use(delegator).from("OrderRole")
                    .where("orderId", orderId, "roleTypeId", "END_USER_CUSTOMER")
                    .queryFirst();
            if (orderRole != null) {
                String partyId = (String) orderRole.get("partyId");
                context.put("partyId", partyId);
            } else {
                String msg = "No OrderRole found for orderId:" + orderId;
                return ServiceUtil.returnFailure(msg);

            }
            orderHeader = EntityQuery.use(delegator).from("OrderHeader").where("orderId", orderId).queryOne();
            if (orderHeader == null) {
                String msg = "No OrderHeader found for orderId:" + orderId;
                return ServiceUtil.returnError(msg);
            }
            Timestamp orderCreatedDate = (Timestamp) orderHeader.get("orderDate");
            context.put("orderCreatedDate", orderCreatedDate);
            List<GenericValue> orderItemList = orderHeader.getRelated("OrderItem", null, null, false);
            ModelService subscriptionModel = dispatcher.getDispatchContext().getModelService("updateContentSubscriptionByProduct");
            for (GenericValue orderItem : orderItemList) {
                BigDecimal qty = orderItem.getBigDecimal("quantity");
                String productId = (String) orderItem.get("productId");
                long productContentCount = EntityQuery.use(delegator).from("ProductContent")
                        .where("productId", productId, "productContentTypeId", "ONLINE_ACCESS")
                        .filterByDate().queryCount();
                if (productContentCount > 0) {
                    context.put("productId", productId);
                    context.put("quantity", Integer.valueOf(qty.intValue()));
                    Map<String, Object> ctx = subscriptionModel.makeValid(context, "IN");
                    dispatcher.runSync("updateContentSubscriptionByProduct", ctx);
                }
            }
        } catch (GenericEntityException e) {
            Debug.logError(e.toString(), module);
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }

    public static Map<String, Object> followNodeChildren(DispatchContext dctx, Map<String, ? extends Object> context) throws GenericServiceException{
        Map<String, Object> result = null;
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Security security = dctx.getSecurity();
        GenericValue userLogin = (GenericValue)context.get("userLogin");
        Locale locale = (Locale) context.get("locale");
        if (!security.hasEntityPermission("CONTENTMGR", "_ADMIN", userLogin)) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentPermissionNotGranted", locale));
        }
        String contentId = (String)context.get("contentId");
        String serviceName = (String)context.get("serviceName");
        String contentAssocTypeId = (String)context.get("contentAssocTypeId");
        List<String> contentAssocTypeIdList = FastList.newInstance();
        if (UtilValidate.isNotEmpty(contentAssocTypeId)) {
             contentAssocTypeIdList = StringUtil.split(contentAssocTypeId, "|");
        }
        if (contentAssocTypeIdList.size() == 0) {
            contentAssocTypeIdList.add("SUB_CONTENT");
        }
        Map<String, Object> ctx = FastMap.newInstance();
        ctx.put("userLogin", userLogin);
        ctx.put("contentAssocTypeIdList", contentAssocTypeIdList);
        try {

            GenericValue content = EntityQuery.use(delegator).from("Content").where("contentId", contentId).queryOne();
            result = followNodeChildrenMethod(content, dispatcher, serviceName, ctx);
        } catch (GenericEntityException e) {
            Debug.logError(e.toString(), module);
            return ServiceUtil.returnError(e.toString());
        }
        return result;
    }
    public static Map<String, Object> followNodeChildrenMethod(GenericValue content,  LocalDispatcher dispatcher, String serviceName, Map<String, Object> context) throws GenericEntityException, GenericServiceException {
        Map<String, Object> result = null;
        String contentId = content.getString("contentId");
        List<String> contentAssocTypeIdList = UtilGenerics.checkList(context.get("contentAssocTypeIdList"));
        Locale locale = (Locale) context.get("locale");
        Set<String> visitedSet = UtilGenerics.checkSet(context.get("visitedSet"));
        if (visitedSet == null) {
            visitedSet = FastSet.newInstance();
            context.put("visitedSet", visitedSet);
        } else {
            if (visitedSet.contains(contentId)) {
                Debug.logWarning("visitedSet already contains:" + contentId, module);
                return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ContentVisitedSet", locale) + contentId);
            } else {
                visitedSet.add(contentId);
            }
        }

        GenericValue userLogin = (GenericValue)context.get("userLogin");
        result = dispatcher.runSync(serviceName, UtilMisc.toMap("content", content, "userLogin", userLogin));

        List<GenericValue> kids = ContentWorker.getAssociatedContent(content, "from", contentAssocTypeIdList, null, null, null);
        for (GenericValue kidContent : kids) {
            followNodeChildrenMethod(kidContent, dispatcher, serviceName, context);
        }
        return result;
    }

    /**
   */
  public static Map<String, Object> persistContentWithRevision(DispatchContext dctx, Map<String, ? extends Object> context) {
      Map<String, Object> result = null;
      Delegator delegator = dctx.getDelegator();
      LocalDispatcher dispatcher = dctx.getDispatcher();
      GenericValue dataResource = null;
      String masterRevisionContentId = (String)context.get("masterRevisionContentId");
      String oldDataResourceId = (String)context.get("drDataResourceId");
      if (UtilValidate.isEmpty(oldDataResourceId)) {
          oldDataResourceId = (String)context.get("dataResourceId");
      }
      if (UtilValidate.isNotEmpty(oldDataResourceId)) {
          try {
              dataResource = EntityQuery.use(delegator).from("DataResource").where("dataResourceId", oldDataResourceId).queryOne();
          } catch (GenericEntityException e) {
              Debug.logError(e.toString(), module);
              return ServiceUtil.returnError(e.toString());
          }
      }

      try {
          ModelService persistContentAndAssocModel = dispatcher.getDispatchContext().getModelService("persistContentAndAssoc");
          Map<String, Object> ctx = persistContentAndAssocModel.makeValid(context, "IN");
          if (dataResource != null) {
              ctx.remove("dataResourceId");
              ctx.remove("drDataResourceId");
          }
          result = dispatcher.runSync("persistContentAndAssoc", ctx);
          String errorMsg = ServiceUtil.getErrorMessage(result);
          if (UtilValidate.isNotEmpty(errorMsg)) {
              return ServiceUtil.returnError(errorMsg);
          }
          String contentId = (String)result.get("contentId");
          List<String> parentList = FastList.newInstance();
          if (UtilValidate.isEmpty(masterRevisionContentId)) {
              Map<String, Object> traversMap = FastMap.newInstance();
              traversMap.put("contentId", contentId);
              traversMap.put("direction", "To");
              traversMap.put("contentAssocTypeId", "COMPDOC_PART");
              Map<String, Object> traversResult = dispatcher.runSync("traverseContent", traversMap);
              parentList = UtilGenerics.checkList(traversResult.get("parentList"));
          } else {
              parentList.add(masterRevisionContentId);
          }

          // Update ContentRevision and ContentRevisonItem
          Map<String, Object> contentRevisionMap = FastMap.newInstance();
          contentRevisionMap.put("itemContentId", contentId);
          contentRevisionMap.put("newDataResourceId", result.get("dataResourceId"));
          contentRevisionMap.put("oldDataResourceId", oldDataResourceId);
          // need committedByPartyId
          for (int i=0; i < parentList.size(); i++) {
              String thisContentId = parentList.get(i);
              contentRevisionMap.put("contentId", thisContentId);
              result = dispatcher.runSync("persistContentRevisionAndItem", contentRevisionMap);
              errorMsg = ServiceUtil.getErrorMessage(result);
              if (UtilValidate.isNotEmpty(errorMsg)) {
                  return ServiceUtil.returnError(errorMsg);
              }
          }
      } catch (GenericServiceException e) {
          Debug.logError(e.toString(), module);
          return ServiceUtil.returnError(e.toString());
      }
      return result;
  }

}
