/* =============================================================================== * * Part of the InfoGlue Content Management Platform (www.infoglue.org) * * =============================================================================== * * Copyright (C) * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2, as published by the * Free Software Foundation. See the file LICENSE.html for more information. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc. / 59 Temple * Place, Suite 330 / Boston, MA 02111-1307 / USA. * * =============================================================================== * * $Id: CategoryController.java,v 1.20 2008/07/03 11:49:04 mattias Exp $ */ package org.infoglue.cms.controllers.kernel.impl.simple; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.exolab.castor.jdo.Database; import org.infoglue.cms.entities.kernel.BaseEntityVO; import org.infoglue.cms.entities.management.Category; import org.infoglue.cms.entities.management.CategoryVO; import org.infoglue.cms.entities.management.impl.simple.CategoryImpl; import org.infoglue.cms.exception.SystemException; import org.infoglue.cms.security.InfoGluePrincipal; import org.infoglue.deliver.util.CacheController; import org.infoglue.deliver.util.Timer; /** * The CategoryController manages all actions related to persistence * and querying for Categories. * * TODO: When we convert have Hibernate manage all of these relationships, it will pull it * TODO: all back with one query and be a helluva lot faster than this pasic implementation * * @author Frank Febbraro (frank@phase2technology.com) */ public class CategoryController extends BaseController { private final static Logger logger = Logger.getLogger(CategoryController.class.getName()); private static final CategoryController instance = new CategoryController(); private static final ContentCategoryController contentCategoryStore = ContentCategoryController.getController(); private static final PropertiesCategoryController propertiesCategoryStore = PropertiesCategoryController.getController(); private static final String findByParent = new StringBuffer("SELECT c ") .append("FROM org.infoglue.cms.entities.management.impl.simple.CategoryImpl c ") .append("WHERE c.parentId = $1 ") .append("ORDER BY c.name ASC").toString(); private static final String findActiveByParent = new StringBuffer("SELECT c ") .append("FROM org.infoglue.cms.entities.management.impl.simple.CategoryImpl c ") .append("WHERE c.parentId = $1 ") .append("AND c.active = $2 ") .append("ORDER BY c.name ASC").toString(); private static final String findRootCategories = new StringBuffer("SELECT c ") .append("FROM org.infoglue.cms.entities.management.impl.simple.CategoryImpl c ") .append("WHERE is_undefined(c.parentId) ") .append("ORDER BY c.name ASC").toString(); private static final String findActiveRootCategories = new StringBuffer("SELECT c ") .append("FROM org.infoglue.cms.entities.management.impl.simple.CategoryImpl c ") .append("WHERE is_undefined(c.parentId) ") .append("AND c.active = $1 ") .append("ORDER BY c.name ASC").toString(); public static CategoryController getController() { return instance; } private CategoryController() {} /** * Find a Category by it's identifier. * * @param id The id of the Category to find * @return The CategoryVO identified by the provided id * @throws SystemException If an error happens */ public CategoryVO findById(Integer id) throws SystemException { return (CategoryVO)getVOWithId(CategoryImpl.class, id); } /** * Find a Category by it's identifier. * * @param id The id of the Category to find * @return The Category identified by the provided id * @throws SystemException If an error happens */ public Category findById(Integer id, Database db) throws SystemException { Category category = null; try { category = (Category)getObjectWithId(CategoryImpl.class, id, db); } catch (Exception e) { if(e.getMessage().indexOf("No lock to release") > -1 || e.getMessage().indexOf("lock without first acquiring the lock") > -1) { logger.warn("An sync issue arose on category: " + id + ":" + e.getMessage()); for(int i=0; i<5; i++) { try { Thread.sleep(10); category = (Category)getObjectWithId(CategoryImpl.class, id, db); logger.warn("It worked out for category: " + id); break; } catch (Exception e2) { logger.warn("Still an issue with loading the category " + id + ":" + e2.getMessage()); } } if(category == null) throw new SystemException("An error occurred when we repeatably tried to fetch categories. Reason:" + e.getMessage(), e); } else throw new SystemException("An error occurred when we tried to fetch a list of categories. Reason:" + e.getMessage(), e); } return category; } /** * Find a Category by it's identifier. * * @param id The id of the Category to find * @return The Category identified by the provided id * @throws SystemException If an error happens */ public CategoryVO findVOById(Integer id, Database db) throws SystemException { return (CategoryVO) getVOWithId(CategoryImpl.class, id, db); } /** * Find a Category by it's identifier. * * @param id The id of the Category to find * @return The Category identified by the provided id * @throws SystemException If an error happens */ public Category findByIdReadOnly(Integer id, Database db) throws SystemException { return (Category)getObjectWithIdAsReadOnly(CategoryImpl.class, id, db); } /** * Find a Category by it's name path. * * @param path The path of the Category to find in the form /categoryName/categoryName/categoryName * @return The CategoryVO identified by the provided path * @throws SystemException If an error happens */ public CategoryVO findByPath(String path) throws SystemException { CategoryVO categoryVO = null; String[] nodes = path.substring(1).split("/"); if(nodes.length > 0) { List rootCategories = findRootCategories(); String name = nodes[0]; categoryVO = getCategoryVOWithNameInList(rootCategories, name); for(int i = 1; i < nodes.length; i++) { categoryVO = getCategoryVOWithNameInList(findByParent(categoryVO.getId()), nodes[i]); } } return categoryVO; } /** * Find a Category by it's name path. * * @param path The path of the Category to find in the form /categoryName/categoryName/categoryName * @return The CategoryVO identified by the provided path * @throws SystemException If an error happens */ public CategoryVO findByPath(String path, Database db) throws SystemException { String key = "" + path; CategoryVO categoryVO = (CategoryVO)CacheController.getCachedObjectFromAdvancedCache("categoryCache", key); if(categoryVO != null) { logger.info("There was an cached categoryVO:" + categoryVO); } else { String[] nodes = path.substring(1).split("/"); if(nodes.length > 0) { List rootCategories = findRootCategoryVOList(db); String name = nodes[0]; categoryVO = getCategoryVOWithNameInList(rootCategories, name); for(int i = 1; i < nodes.length; i++) { categoryVO = getCategoryVOWithNameInList(findByParent(categoryVO.getId(), db), nodes[i]); } } if(categoryVO != null) CacheController.cacheObjectInAdvancedCache("categoryCache", key, categoryVO); } return categoryVO; } /** * Gets a category's full path. * * @return The full path to the category * @throws SystemException If an error happens */ public String getCategoryPath(Integer categoryId) throws SystemException { String path = ""; Database db = CastorDatabaseService.getDatabase(); try { beginTransaction(db); path = getCategoryPath(categoryId, db); commitTransaction(db); } catch (Exception e) { rollbackTransaction(db); } return path; } /** * Gets a category's full path. * * @return The full path to the category * @throws SystemException If an error happens */ public String getCategoryPath(Integer categoryId, Database db) throws SystemException { StringBuffer path = new StringBuffer(); Category category = findById(categoryId, db); if(category != null) { path.insert(0, "/" + category.getName()); while(category.getParentId() != null) { category = findById(category.getParentId(), db); if(category != null) { path.insert(0, "/" + category.getName()); } } } return path.toString(); } /** * Iterates the list of categories and returns the first one that matches your name. * @param categoryVOList * @param name * @return */ private CategoryVO getCategoryVOWithNameInList(List categoryVOList, String name) { CategoryVO categoryVO = null; Iterator categoryVOListIterator = categoryVOList.iterator(); while(categoryVOListIterator.hasNext()) { CategoryVO currentCategoryVO = (CategoryVO)categoryVOListIterator.next(); logger.info("currentCategoryVO:" + currentCategoryVO.getName() + "=" + name); if(currentCategoryVO.getName().equalsIgnoreCase(name)) { categoryVO = currentCategoryVO; break; } } return categoryVO; } /** * Find a List of Categories by parent. * * @param parentId The parent id of the Category to find * @return A list of CategoryVOs that have the provided parentId * @throws SystemException If an error happens */ public List findByParent(Integer parentId) throws SystemException { List params = new ArrayList(); params.add(parentId); return executeQuery(findByParent, params); } /** * Find a List of Categories by parent. * * @param parentId The parent id of the Category to find * @return A list of CategoryVOs that have the provided parentId * @throws SystemException If an error happens */ public List<CategoryVO> findByParent(Integer parentId, Database db) throws SystemException { List<CategoryVO> list = null; List params = new ArrayList(); params.add(parentId); try { list = toVOList(executeQueryReadOnly(findByParent, params, db)); } catch (Exception e) { if(e.getMessage().indexOf("No lock to release") > -1 || e.getMessage().indexOf("lock without first acquiring the lock") > -1) { logger.warn("An sync issue arose on: " + parentId + ":" + e.getMessage()); for(int i=0; i<5; i++) { try { Thread.sleep(10); list = toVOList(executeQueryReadOnly(findByParent, params, db)); logger.warn("It worked out for category: " + parentId); break; } catch (Exception e2) { logger.warn("Still an issue with loading the category " + parentId + ":" + e2.getMessage()); } } if(list == null) throw new SystemException("An error occurred when we repeatably tried to fetch categories. Reason:" + e.getMessage(), e); } else throw new SystemException("An error occurred when we tried to fetch a list of categories. Reason:" + e.getMessage(), e); } return list; } /** * Find a List of active Categories by parent. * * @param parentId The parent id of the Category to find * @return A list of CategoryVOs that have the provided parentId * @throws SystemException If an error happens */ public List<CategoryVO> getActiveCategoryVOListByParent(Integer parentId, Database db) throws SystemException { String categoriesKey = "childCategories_" + parentId + "_active"; List<CategoryVO> categories = (List<CategoryVO>)CacheController.getCachedObjectFromAdvancedCache("categoriesCache", categoriesKey); if(categories != null) { logger.info("There was an cached categories:" + categories); } else { if(logger.isInfoEnabled()) logger.info("Querying for categories:" + categoriesKey); List params = new ArrayList(); params.add(parentId); params.add(Boolean.TRUE); categories = toVOList(executeQueryReadOnly(findActiveByParent, params, db)); if(categories != null && categories.size() > 0) { CacheController.cacheObjectInAdvancedCache("categoriesCache", categoriesKey, categories); } else { CacheController.cacheObjectInAdvancedCache("categoriesCache", categoriesKey, new ArrayList<CategoryVO>()); } } return categories; } /** * Find a List of active Categories by parent. * * @param parentId The parent id of the Category to find * @return A list of CategoryVOs that have the provided parentId * @throws SystemException If an error happens */ public List findActiveByParent(Integer parentId) throws SystemException { String categoriesKey = "childCategories_" + parentId + "_active"; List categories = (List)CacheController.getCachedObjectFromAdvancedCache("categoriesCache", categoriesKey); if(categories != null) { logger.info("There was an cached categories:" + categories); } else { if(logger.isInfoEnabled()) logger.info("Querying for categories:" + categoriesKey); List params = new ArrayList(); params.add(parentId); params.add(Boolean.TRUE); categories = executeQuery(findActiveByParent, params); if(categories != null && categories.size() > 0) { CacheController.cacheObjectInAdvancedCache("categoriesCache", categoriesKey, categories); } else { CacheController.cacheObjectInAdvancedCache("categoriesCache", categoriesKey, new ArrayList()); } } return categories; } /** * Find a List of active Categories by parent. * * @param parentId The parent id of the Category to find * @return A list of CategoryVOs that have the provided parentId * @throws SystemException If an error happens */ public List<CategoryVO> getActiveByParent(Integer parentId, Database db) throws SystemException { String categoriesKey = "childCategories_" + parentId + "_active"; List categories = (List)CacheController.getCachedObjectFromAdvancedCache("categoriesCache", categoriesKey); if(categories != null) { logger.info("There was an cached categories:" + categories); } else { if(logger.isInfoEnabled()) logger.info("Querying for categories:" + categoriesKey); List params = new ArrayList(); params.add(parentId); params.add(Boolean.TRUE); categories = toVOList(executeQueryReadOnly(findActiveByParent, params, db)); if(categories != null && categories.size() > 0) { CacheController.cacheObjectInAdvancedCache("categoriesCache", categoriesKey, categories); } else { CacheController.cacheObjectInAdvancedCache("categoriesCache", categoriesKey, new ArrayList()); } } return categories; } /** * Find a Category with it's children populated. * * @param id The id of the Category to find * @return A list of CategoryVOs that are at the root of the category tree * @throws SystemException If an error happens */ public CategoryVO findWithChildren(Integer id) throws SystemException { CategoryVO c = findById(id); c.setChildren(findByParent(c.getId())); return c; } /** * Find a Category with it's children populated. * * @param id The id of the Category to find * @return A list of CategoryVOs that are at the root of the category tree * @throws SystemException If an error happens */ public CategoryVO findWithChildren(Integer id, Database db) throws SystemException { Category c = findById(id, db); c.getValueObject().setChildren(findByParent(c.getId(), db)); return c.getValueObject(); } /** * Find a List of Categories that have no parent. * * @return A list of CategoryVOs that are at the root of the category tree * @throws SystemException If an error happens */ public List findRootCategories() throws SystemException { return executeQuery(findRootCategories); } /** * Find a List of Categories that have no parent. * * @return A list of CategoryVOs that are at the root of the category tree * @throws SystemException If an error happens */ public List findRootCategories(Database db) throws SystemException { return executeQuery(findRootCategories, db); } /** * Find a List of Categories that have no parent. * * @return A list of CategoryVOs that are at the root of the category tree * @throws SystemException If an error happens */ public List<CategoryVO> findRootCategoryVOList(Database db) throws SystemException { String categoriesKey = "rootCategories"; List<CategoryVO> categories = (List)CacheController.getCachedObjectFromAdvancedCache("categoriesCache", categoriesKey); if(categories != null) { logger.info("There was an cached categories:" + categories); } else { if(logger.isInfoEnabled()) logger.info("Querying for categories:" + categoriesKey); List categoryImpls = executeQueryReadOnly(findRootCategories, db); if(categoryImpls != null) { categories = toVOList(categoryImpls); CacheController.cacheObjectInAdvancedCache("categoriesCache", categoriesKey, categories); } } return categories; //List categories = executeQueryReadOnly(findRootCategories, db); //return (categories != null) ? toVOList(categories) : null; } /** * Find a list of all Categories in the system. * * @return A list of CategoryVOs starting at the root of the category tree * @throws SystemException If an error happens */ /* public List findAllActiveCategories() throws SystemException { List params = new ArrayList(); params.add(Boolean.TRUE); List roots = executeQuery(findActiveRootCategories, params); for (Iterator iter = roots.iterator(); iter.hasNext();) { CategoryVO root = (CategoryVO) iter.next(); root.setChildren(findAllActiveChildren(root.getId())); } return roots; } */ /** * Find a list of all Categories in the system. * * @return A list of CategoryVOs starting at the root of the category tree * @throws SystemException If an error happens */ public List<CategoryVO> getAllActiveCategories() throws SystemException { List<CategoryVO> roots = new ArrayList<CategoryVO>(); Database db = CastorDatabaseService.getDatabase(); beginTransaction(db); try { List params = new ArrayList(); params.add(Boolean.TRUE); roots = toVOList(executeQueryReadOnly(findActiveRootCategories, params, db)); for (Iterator iter = roots.iterator(); iter.hasNext();) { CategoryVO root = (CategoryVO) iter.next(); root.setChildren(getAllActiveChildren(root.getId(), db)); } rollbackTransaction(db); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction:" + e); logger.warn("An error occurred so we should not complete the transaction:" + e, e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return roots; } /** * Find a list of all Categories in the system. * * @return A list of CategoryVOs starting at the root of the category tree * @throws SystemException If an error happens */ public List findAllActiveCategories(boolean includePaths) throws SystemException { List params = new ArrayList(); params.add(Boolean.TRUE); List roots = executeQuery(findActiveRootCategories, params); for (Iterator iter = roots.iterator(); iter.hasNext();) { CategoryVO root = (CategoryVO) iter.next(); if(includePaths) { String categoryPath = this.getCategoryPath(root.getCategoryId()); root.setCategoryPath(categoryPath); } root.setChildren(findAllActiveChildren(root.getId(), includePaths)); } return roots; } /** * Find a list of all Categories in the system. * * @return A list of CategoryVOs starting at the root of the category tree * @throws SystemException If an error happens */ public List<CategoryVO> getAllActiveCategories(boolean includePaths) throws SystemException { List<CategoryVO> roots = new ArrayList<CategoryVO>(); Database db = CastorDatabaseService.getDatabase(); beginTransaction(db); try { List params = new ArrayList(); params.add(Boolean.TRUE); roots = executeQueryReadOnly(findActiveRootCategories, params, db); for (Iterator iter = roots.iterator(); iter.hasNext();) { CategoryVO root = (CategoryVO) iter.next(); if(includePaths) { String categoryPath = this.getCategoryPath(root.getCategoryId(), db); root.setCategoryPath(categoryPath); } root.setChildren(getAllActiveChildren(root.getId(), includePaths, db)); } rollbackTransaction(db); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction:" + e); logger.warn("An error occurred so we should not complete the transaction:" + e, e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return roots; } /** * Finds all authorized categories parent id, recursively until no children are found. * * @return A list of children nodes, with thier children populated */ public List getAuthorizedActiveChildren(Integer parentId, InfoGluePrincipal infogluePrincipal) throws SystemException { List children = findActiveByParent(parentId); for (Iterator iter = children.iterator(); iter.hasNext();) { CategoryVO child = (CategoryVO) iter.next(); if(!getIsAccessApproved(child.getCategoryId(), infogluePrincipal)) { iter.remove(); } List subChildren = findAllActiveChildren(child.getId()); Iterator subChildrenIterator = subChildren.iterator(); while(subChildrenIterator.hasNext()) { CategoryVO subChild = (CategoryVO) subChildrenIterator.next(); if(getIsAccessApproved(subChild.getCategoryId(), infogluePrincipal)) { child.getChildren().add(subChild); } } } return children; } /** * Finds all children for a given parent id, recursively until no children are found. * * @return A list of children nodes, with thier children populated */ public List<CategoryVO> getActiveChildrenCategoryVOList(Integer parentId) throws SystemException { List<CategoryVO> children = new ArrayList<CategoryVO>(); Database db = CastorDatabaseService.getDatabase(); beginTransaction(db); try { children = getActiveChildrenCategoryVOList(parentId, db); rollbackTransaction(db); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction:" + e); logger.warn("An error occurred so we should not complete the transaction:" + e, e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return children; } /** * Finds all children for a given parent id, recursively until no children are found. * * @return A list of children nodes, with thier children populated */ public List<CategoryVO> getActiveChildrenCategoryVOList(Integer parentId, Database db) throws SystemException { Timer t = new Timer(); List<CategoryVO> children = getActiveCategoryVOListByParent(parentId, db); for (Iterator iter = children.iterator(); iter.hasNext();) { CategoryVO child = (CategoryVO) iter.next(); child.setChildren(getActiveChildrenCategoryVOList(child.getId(), db)); } /* List children = findActiveByParent(parentId); for (Iterator iter = children.iterator(); iter.hasNext();) { CategoryVO child = (CategoryVO) iter.next(); child.setChildren(findAllActiveChildren(child.getId())); } */ return children; } /** * Finds all children for a given parent id, recursively until no children are found. * * @return A list of children nodes, with thier children populated */ public List findAllActiveChildren(Integer parentId) throws SystemException { return getActiveChildrenCategoryVOList(parentId); /* Timer t = new Timer(); List children = findActiveByParent(parentId); for (Iterator iter = children.iterator(); iter.hasNext();) { CategoryVO child = (CategoryVO) iter.next(); child.setChildren(findAllActiveChildren(child.getId())); } return children; */ } /** * Finds all children for a given parent id, recursively until no children are found. * * @return A list of children nodes, with thier children populated */ public List<CategoryVO> getAllActiveChildren(Integer parentId, Database db) throws SystemException { Timer t = new Timer(); List<CategoryVO> children = getActiveCategoryVOListByParent(parentId, db); for (Iterator iter = children.iterator(); iter.hasNext();) { CategoryVO child = (CategoryVO) iter.next(); child.setChildren(getAllActiveChildren(child.getId(), db)); } return children; } /** * Finds all children for a given parent id, recursively until no children are found. * * @return A list of children nodes, with thier children populated */ public List findAllActiveChildren(Integer parentId, boolean includePaths) throws SystemException { List children = findActiveByParent(parentId); for (Iterator iter = children.iterator(); iter.hasNext();) { CategoryVO child = (CategoryVO) iter.next(); if(includePaths) { String categoryPath = CategoryController.getController().getCategoryPath(child.getCategoryId()); child.setCategoryPath(categoryPath); } child.setChildren(findAllActiveChildren(child.getId())); } return children; } /** * Finds all children for a given parent id, recursively until no children are found. * * @return A list of children nodes, with thier children populated */ public List<CategoryVO> getAllActiveChildren(Integer parentId, boolean includePaths, Database db) throws SystemException { List children = getActiveByParent(parentId, db); for (Iterator iter = children.iterator(); iter.hasNext();) { CategoryVO child = (CategoryVO) iter.next(); if(includePaths) { String categoryPath = CategoryController.getController().getCategoryPath(child.getCategoryId(), db); child.setCategoryPath(categoryPath); } child.setChildren(getAllActiveChildren(child.getId(), db)); } return children; } /** * Saves a CategoryVO whether it is new or not. * * @param c The CategoryVO to save * @return The saved CategoryVO * @throws SystemException If an error happens */ public Category save(CategoryVO c, Database db) throws SystemException { return (c.isUnsaved()) ? create(c, db) : (Category)updateEntity(CategoryImpl.class, c, db); } /** * Creates a Category from a CategoryVO */ private Category create(CategoryVO c, Database db) throws SystemException { CategoryImpl impl = new CategoryImpl(c); return ((CategoryImpl)createEntity(impl)); } /** * Saves a CategoryVO whether it is new or not. * * @param c The CategoryVO to save * @return The saved CategoryVO * @throws SystemException If an error happens */ public CategoryVO save(CategoryVO c) throws SystemException { return (c.isUnsaved()) ? create(c) : (CategoryVO)updateEntity(CategoryImpl.class, c); } /** * Creates a Category from a CategoryVO */ private CategoryVO create(CategoryVO c) throws SystemException { CategoryImpl impl = new CategoryImpl(c); return ((CategoryImpl)createEntity(impl)).getValueObject(); } /** * Moves a CategoryVO to a different parent category * * @param categoryId The id of the CategoryVO to move * @param newParentId The id of the parent to move the CategoryVO * @return The saved CategoryVO * @throws SystemException If an error happens */ public CategoryVO moveCategory(Integer categoryId, Integer newParentId) throws SystemException { CategoryVO category = findById(categoryId); category.setParentId(newParentId); return save(category); } /** * Deletes a CategoryVO, and all children. * * TODO: The reason we delete the ContentCategory first is that once the Category * TODO: is gone, Castor will never find them again. When we move to Hibernate we * TODO: can probalby put this afterwards, in it's more logical place. * * @param id The id of the Category to delete * @throws SystemException If an error happens */ public void delete(Integer id) throws SystemException { contentCategoryStore.deleteByCategory(id); propertiesCategoryStore.deleteByCategory(id); deleteEntity(CategoryImpl.class, id); deleteChildren(id); } /** * Deletes the children of the supplied category */ private void deleteChildren(Integer id) throws SystemException { List children = findByParent(id); for (Iterator iter = children.iterator(); iter.hasNext();) delete(((CategoryVO) iter.next()).getId()); } /** * Implemented for BaseController */ public BaseEntityVO getNewVO() { return new CategoryVO(); } /** * This method returns true if the user should have access to the contentTypeDefinition sent in. */ public boolean getIsAccessApproved(Integer categoryId, InfoGluePrincipal infoGluePrincipal) throws SystemException { logger.info("getIsAccessApproved for " + categoryId + " AND " + infoGluePrincipal); boolean hasAccess = false; Database db = CastorDatabaseService.getDatabase(); beginTransaction(db); try { hasAccess = AccessRightController.getController().getIsPrincipalAuthorized(db, infoGluePrincipal, "Category.Read", categoryId.toString()); commitTransaction(db); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction:" + e, e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return hasAccess; } //------------- public void compareAndCompleteCategoryLists(List remoteCategoryVOList, List<CategoryVO> allLocalCategories, CategoryVO localParentCategory, Map handledRemoteCategoryPaths, Map request) throws SystemException { Iterator remoteCategoryVOListIterator = remoteCategoryVOList.iterator(); while(remoteCategoryVOListIterator.hasNext()) { CategoryVO remoteCategoryVO = (CategoryVO)remoteCategoryVOListIterator.next(); boolean categoryExists = false; CategoryVO localCategoryVO = null; Iterator allLocalCategoriesIterator = allLocalCategories.iterator(); while(allLocalCategoriesIterator.hasNext()) { localCategoryVO = (CategoryVO)allLocalCategoriesIterator.next(); if(localCategoryVO.getName().equals(remoteCategoryVO.getName())) { categoryExists = true; break; } } boolean skipLocalCategory = false; if(!categoryExists) { Database db = CastorDatabaseService.getDatabase(); try { beginTransaction(db); String remoteParentPath = remoteCategoryVO.getCategoryPath(); String isCategorySelected = (String)request.get(remoteParentPath + "_transfer"); if(isCategorySelected != null && isCategorySelected.equals("true")) { skipLocalCategory = true; handleSubCategories(localParentCategory, remoteCategoryVO, handledRemoteCategoryPaths, request, db); } commitTransaction(db); } catch (Exception e) { e.printStackTrace(); rollbackTransaction(db); } } if(remoteCategoryVO.getChildren() != null && remoteCategoryVO.getChildren().size() > 0) { if(localCategoryVO != null && !skipLocalCategory) { compareAndCompleteCategoryLists(remoteCategoryVO.getChildren(), localCategoryVO.getChildren(), localCategoryVO, handledRemoteCategoryPaths, request); } else { compareAndCompleteCategoryLists(remoteCategoryVO.getChildren(), new ArrayList(), null, handledRemoteCategoryPaths, request); } } } } public void handleSubCategories(CategoryVO localParentCategory, CategoryVO remoteCategoryVO, Map handledRemoteCategoryPaths, Map request, Database db) throws SystemException { String isCategorySelected = (String)request.get(remoteCategoryVO.getCategoryPath() + "_transfer"); if(isCategorySelected != null && isCategorySelected.equals("true")) { if(handledRemoteCategoryPaths.containsKey(remoteCategoryVO.getCategoryPath())) { logger.info("Category with path " + remoteCategoryVO.getCategoryPath() + " was allready handled."); } else { logger.info("Creating local version of:" + remoteCategoryVO + " under " + localParentCategory); remoteCategoryVO.setCategoryId(null); if(localParentCategory != null) remoteCategoryVO.setParentId(localParentCategory.getId()); Category newLocalCategory = CategoryController.getController().save(remoteCategoryVO, db); handledRemoteCategoryPaths.put(remoteCategoryVO.getCategoryPath(), "true"); List subCategories = remoteCategoryVO.getChildren(); Iterator subCategoriesIterator = subCategories.iterator(); while(subCategoriesIterator.hasNext()) { CategoryVO subCategory = (CategoryVO)subCategoriesIterator.next(); logger.info("subCategory:[" + subCategory + "]"); handleSubCategories(newLocalCategory.getValueObject(), subCategory, handledRemoteCategoryPaths, request, db); } } } } }