/* ================================================================== * Created [2009-4-27 下午11:32:55] by Jon.King * ================================================================== * TSS * ================================================================== * mailTo:jinpujun@hotmail.com * Copyright (c) Jon.King, 2009-2012 * ================================================================== */ package com.jinhe.tss.portal.service.impl; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dom4j.Document; import org.springframework.beans.factory.annotation.Autowired; import com.jinhe.tss.core.Global; import com.jinhe.tss.core.cachepool.CacheManager; import com.jinhe.tss.core.cachepool.Cacheable; import com.jinhe.tss.core.cachepool.CacheableKey; import com.jinhe.tss.core.cachepool.ICacheLoader; import com.jinhe.tss.core.cachepool.IPool; import com.jinhe.tss.core.cachepool.TimeWrapper; import com.jinhe.tss.core.exception.BusinessException; import com.jinhe.tss.core.sso.Environment; import com.jinhe.tss.core.sso.context.Context; import com.jinhe.tss.core.util.BeanUtil; import com.jinhe.tss.core.util.FileHelper; import com.jinhe.tss.core.util.XMLDocUtil; import com.jinhe.tss.portal.PortalConstants; import com.jinhe.tss.portal.dao.INavigatorDao; import com.jinhe.tss.portal.engine.PersonalManager; import com.jinhe.tss.portal.engine.PortalGenerator; import com.jinhe.tss.portal.engine.model.PageNode; import com.jinhe.tss.portal.engine.model.PortalNode; import com.jinhe.tss.portal.entity.Decorator; import com.jinhe.tss.portal.entity.Layout; import com.jinhe.tss.portal.entity.Navigator; import com.jinhe.tss.portal.entity.PersonalPage; import com.jinhe.tss.portal.entity.PersonalTheme; import com.jinhe.tss.portal.entity.Portal; import com.jinhe.tss.portal.entity.PortalStructure; import com.jinhe.tss.portal.entity.Theme; import com.jinhe.tss.portal.entity.ThemeInfo; import com.jinhe.tss.portal.entity.ThemeInfoId; import com.jinhe.tss.portal.helper.ElementHelper; import com.jinhe.tss.portal.helper.PortalStructureWrapper; import com.jinhe.tss.portal.service.IPortalService; /** * 注: PortalService 继承了ICacheLoader接口,而ICacheLoader接口执行loadCacheObject时会重新new 一个PortalService出来 */ public class PortalService extends PortalRelationService implements IPortalService, ICacheLoader { @Autowired private INavigatorDao menuDao; //* ****************************************** 获取门户结构操作 ****************************************************** public PortalStructure getPortalStructureById(Long id) { return portalDao.getEntity(id); } public List<?> getAllPortalStructures() { return portalDao.getEntities("from PortalStructure o order by o.decode "); } public List<?> getTargetPortalStructures() { return portalDao.getEntities("from PortalStructure o where o.type <> 3 order by o.decode "); } public List<?> getActivePortals() { return portalDao.getEntities("from PortalStructure o where o.disabled <> 1 and o.type = 0 order by o.decode "); } public List<?> getActivePagesByPortal(Long portalId) { return portalDao.getEntities("from PortalStructure o where o.portalId = ? and o.disabled <> 1" + " and o.type <> 3 and o.type <> 0 order by o.decode ", portalId); } public List<?> getPortalStructuresByPortal(Long portalId) { return portalDao.getEntities("from PortalStructure o where o.portalId = ? and o.disabled <> 1 " + "and o.type <> 0 order by o.decode ", portalId); } //* ********************************************* 读取组装门户所需数据 ******************************************************** public PortalNode getPortal(Long portalId, Long selectThemeId, String method) { Portal portal = portalDao.getPortalById(portalId); portalDao.evict(portal); if( selectThemeId != null ) { portal.setThemeId(selectThemeId); } // 如果是匿名访问, 则直接访问默认门户 if(Context.getIdentityCard().isAnonymous()) { return getNormalPortal(portal); } PersonalTheme personalTheme = portalDao.getPersonalTheme(portalId); if(personalTheme != null) { Long personalThemeId = personalTheme.getId(); portal.setPersonalThemeId(personalThemeId); String hql = "from PersonalPage o where o.userId = ? and o.portalId = ? and o.themeId = ?"; List<?> list = portalDao.getEntities(hql, Environment.getOperatorId(), portalId, personalThemeId); for( Object temp : list ){ PersonalPage pp = (PersonalPage) temp; portal.getPersonalPageXMLs().add(XMLDocUtil.dataXml2Doc(pp.getConfigInfo())); } } return getPersonalPortal(portal); } // 缓存池里如果get不到,会自动调用ICacheLoader.reloadCacheObject()方法生成所需的对象。 private PortalNode getNormalPortal(Portal portal) { CacheableKey portalCacheKey = portal.getDefaultKey(); IPool pool = CacheManager.getInstance().getCachePool(PortalConstants.PORTAL_TREE_CACHE); PortalNode portalNode = (PortalNode) pool.getObject(portalCacheKey).getValue(); return (PortalNode) portalNode.clone(); } public PortalNode getPersonalPortal(Portal portal) { List<Document> personalPageXMLs = portal.getPersonalPageXMLs(); if( personalPageXMLs.isEmpty() ) { return getNormalPortal(portal); // 如果该用户没有自定义页面,则直接返回默认门户的拷贝 } // 先从自定义门户缓存池中获取自定义门户,取不到再取默认的 CacheableKey personalKey = portal.getPersonalKey(); IPool personalPool = CacheManager.getInstance().getCachePool(PortalConstants.PERSONAL_PORTAL_TREE_CACHE); Cacheable item = personalPool.getObject(personalKey); if(item != null){ return (PortalNode) item.getValue(); } PortalNode copy = getNormalPortal(portal); // 加入个性化定制信息 PersonalManager personalManager = new PersonalManager(copy, personalPageXMLs, portalDao); log.info("-------------------------自定义前-------------------------"); log.info(personalManager.genetateStructureXML((PageNode) copy.getChildren().toArray()[0])); log.info("------------------------------------------------------"); PortalNode personal = personalManager.generatePersonalPortal(); // 执行自定义 log.info("-------------------------自定义后-------------------------"); log.info(personalManager.genetateStructureXML((PageNode) copy.getChildren().toArray()[0])); log.info("------------------------------------------------------"); //缓存个性化PortalNode personalPool.putObject(personalKey, personal); return personal; } public Cacheable reloadCacheObject(Cacheable item) { // 判断PortalService是spring ioc托管的还是缓存模块new出来的,只有托管的才能正常注入portalDao if(portalDao == null) { ICacheLoader loader = (ICacheLoader)Global.getContext().getBean("PortalService"); return loader.reloadCacheObject(item); } CacheableKey cKey = (CacheableKey) item.getKey(); String key = cKey.getKey(); // portalId_themeId int _index = key.indexOf("_"); Long portalId = Long.valueOf(key.substring(0, _index)); Long themeId = Long.valueOf(key.substring(_index + 1)); return new TimeWrapper(cKey, getPortalNode(portalId, themeId)); } @SuppressWarnings("unchecked") private PortalNode getPortalNode(Long portalId, Long themeId){ List<?> themeInfos = portalDao.getEntities("from ThemeInfo t where t.id.themeId = ?", themeId); Map<Long, ThemeInfo> themeInfosMap = new HashMap<Long, ThemeInfo>(); for(Object temp : themeInfos){ ThemeInfo info = (ThemeInfo) temp; themeInfosMap.put(info.getId().getPortalStructureId(), info); } // 根据portalId获取一个完整的门户结构,并且根据传入的themeId获取各个门户结构相对应该主题的主题信息,设置到门户结构对象上 String hql = " from PortalStructure o where o.portalId = ? and o.disabled <> 1 order by o.decode "; List<PortalStructure> structuresList = (List<PortalStructure>) portalDao.getEntities(hql, portalId); PortalStructure rootps = portalDao.getRootPortalStructure(portalId); structuresList.remove(rootps); // 去除根节点 portalDao.evict(rootps); for( PortalStructure ps : structuresList ){ portalDao.evict(ps); ThemeInfo info = themeInfosMap.get(ps.getId()); ps.setDecoratorId(info != null ? info.getDecoratorId() : portalDao.getDefaultDecorator().getId()); /* portlet实例: portlet参数取存于门户结构中的参数(ps.getParameters()),修饰器参数取主题中的(info.getParameters()) portlet和修饰器的参数分开来放,如果portlet实例的参数也存放于主题信息中的话,那么修改参数将非常麻烦,需要一个个主题修改过来。 */ if(ps.isPortletInstanse()) { String portletParam = ElementHelper.getPortletInstanseConfig(ps.getParameters()); String docoratorParam = "<decorator/>" ; if( info != null ) { docoratorParam = ElementHelper.getDecoratorInstanseConfig(info.getParameters()); } ps.setParameters(ElementHelper.createPortletInstanseConfig(portletParam, docoratorParam)); } // 页面和版面的参数取各主题信息的。 页面和版面的布局器和修饰器取默认主题中相应布局器和修饰器 else{ ps.setDefinerId (info != null ? info.getLayoutId() : portalDao.getDefaultLayout().getId()); ps.setParameters(info != null ? info.getParameters() : "<params><layout/><portlet/><decorator/></params>"); } } Portal portal = portalDao.getPortalById(portalId); PortalStructureWrapper root = new PortalStructureWrapper(rootps, portal); Object[] elements = portalDao.getPortalElements(portalId, themeId); PortalNode node = PortalGenerator.genPortalNode(root, structuresList, elements); if(node == null) { throw new BusinessException("获取门户结构树【PortalGenerator.genPortalNode()】失败!"); } return node; } public PortalStructure getPoratalStructure(Long psId) { PortalStructure ps = portalDao.getEntity(psId); Portal portal = portalDao.getPortalById(ps.getPortalId()); if(ps.isRootPortal()) { ps = new PortalStructureWrapper(ps, portal); } else { // 加载主题信息 ThemeInfoId themeInfoId = new ThemeInfoId(portal.getCurrentThemeId(), psId); ThemeInfo themeInfo = (ThemeInfo) portalDao.getEntity(ThemeInfo.class, themeInfoId); if( themeInfo == null ) { //如果该门户结构在当前主题下找不到主题信息,则取默认的修饰和布局 Layout defaultLayout = portalDao.getDefaultLayout(); Decorator defaultDecorator = portalDao.getDefaultDecorator(); themeInfo = new ThemeInfo(); themeInfo.setDecoratorId(defaultDecorator.getId()); themeInfo.setDecoratorName(defaultDecorator.getName()); themeInfo.setLayoutId(defaultLayout.getId()); themeInfo.setLayoutName(defaultLayout.getName()); } ps.setDecoratorId(themeInfo.getDecoratorId()); ps.setDecoratorName(themeInfo.getDecoratorName()); // 如果是portlet实例,则取主题的修饰器参数和门户结构上的portlet参数做为新的参数配置。(portlet参数不分主题,只保存在门户结构表中)。 if( ps.isPortletInstanse() ) { String portletParam = ElementHelper.getPortletInstanseConfig(ps.getParameters()); String docoratorParam = ElementHelper.getDecoratorInstanseConfig(themeInfo.getParameters()); ps.setParameters(ElementHelper.createPortletInstanseConfig(portletParam, docoratorParam)); } // 只有不是portlet实例才直接用主题表中的参数信息(页面、版面的布局修饰器等信息) else { ps.setDefinerId(themeInfo.getLayoutId()); ps.setDefinerName(themeInfo.getLayoutName()); ps.setParameters(themeInfo.getParameters()); } } return ps; } public PortalStructure createPortalStructure(PortalStructureWrapper psw) { Portal portal; if( psw.isRootPortal() ) { // 新增门户根节点 portal = (Portal) portalDao.createObject(psw.getPortal()); //先保存Portal对象,得到生成的Id psw.setPortalId(portal.getId()); Long newThemeId = saveTheme(psw).getId(); portal.setThemeId(newThemeId); portal.setCurrentThemeId(newThemeId); portalDao.update(portal); /* 默认新增一个菜单根节点,专门用于新建门户的菜单管理 */ Navigator portalMenu = new Navigator(); portalMenu.setType(Navigator.TYPE_MENU); portalMenu.setName(psw.getName()); portalMenu.setPortalId(psw.getPortalId()); portalMenu.setParentId(PortalConstants.ROOT_ID); portalMenu.setSeqNo(menuDao.getNextSeqNo(PortalConstants.ROOT_ID)); menuDao.saveMenu(portalMenu); } else { portal = portalDao.getPortalById(psw.getPortalId()); } PortalStructure returnEntity = savePortalStructure(psw.getPortalStructure()); psw = new PortalStructureWrapper(returnEntity, portal); saveThemeInfo(psw); return psw; } public PortalStructure updatePortalStructure(PortalStructureWrapper psw) { PortalStructure returnEntity = savePortalStructure(psw.getPortalStructure()); Portal portal = portalDao.getPortalById(psw.getPortalId()); psw = new PortalStructureWrapper(returnEntity, portal); saveThemeInfo(psw); return psw; } /** * 因为decode生成需要拦截dao的方法(执行前拦截),如果在dao中设置seqNo,会导致拦截时还没有生成seqNo。 */ private PortalStructure savePortalStructure(PortalStructure ps){ if(ps.getId() == null) { ps.setSeqNo(portalDao.getNextSeqNo(ps.getParentId())); } ps = portalDao.savePortalStructure(ps); if(ps.getCode() == null) { ps.setCode(ps.getPortalId() + "_" + ps.getId()); } return ps; } /** * 保存主题 * @param psw * @return */ private Theme saveTheme(PortalStructureWrapper psw){ Theme theme = new Theme(); theme.setName(psw.getThemeName()); theme.setPortalId(psw.getPortalId()); return (Theme) portalDao.createObject(theme); } /** * 保存主题信息。 * 注:保存门户结构主题信息的同时,门户结构中也保存了最近一次修改的主题信息。 * @param psw */ private void saveThemeInfo(PortalStructureWrapper psw){ // 门户节点没有主题信息 if(psw.isRootPortal()) return; ThemeInfo info = new ThemeInfo(); info.setId(new ThemeInfoId(psw.getCurrentThemeId(), psw.getId())); info.setDecoratorId(psw.getDecoratorId()); info.setDecoratorName(psw.getDecoratorName()); if( psw.isPage() || psw.isSection() ) { // 页面、版面 info.setLayoutId(psw.getDefinerId()); info.setLayoutName(psw.getDefinerName()); } /* 参数信息即可保存于门户结构上,也可保存于主题信息。 * 如果考虑主题自定义,则优先使用存于主题上的各组件参数信息。*/ info.setParameters(psw.getParameters()); portalDao.createObject(info); } public void delete(Long id) { PortalStructure ps = portalDao.getEntity(id); // 删除一个枝 List<PortalStructure> branch = portalDao.getChildrenById(id); for( PortalStructure node : branch ) { portalDao.deletePortalStructure(node); } // 如果删除的是门户,则: if( ps.isRootPortal() ) { Long portalId = ps.getPortalId(); // 1、删除门户的菜单信息 List<?> menus = portalDao.getEntities("from Navigator o where o.portalId=?", portalId); for( Object temp : menus ){ menuDao.deleteMenu((Navigator) temp); } // 2、删除主题信息 portalDao.deleteAll(getThemesByPortal(portalId)); // 3、则将原门户的上传文件一并删除,删除上传文件前需确保所有逻辑数据已经删除 FileHelper.deleteFilesInDir("", ps.getPortalResourceFileDir()); } } public void disable(Long id, Integer disabled) { PortalStructure ps = portalDao.getEntity(id); List<PortalStructure> list; // 如果是启用或者操作的是门户根节点,则处理操作节点以下的所有子节点 if(disabled.equals(PortalConstants.TRUE) || ps.isRootPortal()){ list = portalDao.getChildrenById(id, PortalConstants.PORTAL_STOP_OPERRATION ); } else { // 启用向上 list = portalDao.getParentsById(id, PortalConstants.PORTAL_START_OPERRATION); } for( PortalStructure entity : list ){ entity.setDisabled(disabled); portalDao.update(entity); } } public void order(Long id, Long targetId, int direction) { portalDao.sort(id, targetId, direction); } public void move(Long psId, Long targetId, Long targetPortalId) { PortalStructure ps = portalDao.getEntity(psId); // 判断是否是跨门户移动,如果portalId不相等,则说明是跨门户移动 boolean isAcrossPortal = !ps.getPortalId().equals(targetPortalId); List<PortalStructure> sons = portalDao.getChildrenById(psId, PortalConstants.PORTAL_DEL_OPERRATION); ps.setSeqNo(portalDao.getNextSeqNo(targetId)); ps.setParentId(targetId); portalDao.movePortalStructure(ps); // 如果是跨门户移动,则删除和本子节点相关的菜单和主题信息 if( isAcrossPortal ){ for( PortalStructure temp : sons ){ temp.setPortalId(targetPortalId); portalDao.updateWithoutFlush(temp); clearRelation(temp.getId()); } // 如果是跨门户且复制的是页面,则一带将页面的资源复制过去 if(ps.isPage()){ PortalStructure targetPortal = portalDao.getRootPortalStructure(targetPortalId); PortalStructure sourcePortal = portalDao.getRootPortalStructure(ps.getPortalId()); copyPageResources(sourcePortal, targetPortal, ps.getSupplement()); } } //如果目标节点是停用的,则移动的枝全部停用 PortalStructure parent = portalDao.getEntity(targetId); if(parent.getDisabled().equals(PortalConstants.TRUE)) { disable(psId, PortalConstants.TRUE); } } private void clearRelation(Long id) { portalDao.deleteAll(portalDao.getEntities("from Navigator o where o.targetId = ? or o.contentId = ?", id, id)); portalDao.deleteAll(portalDao.getEntities("from ThemeInfo o where o.id.portalStructureId = ?", id)); } /* 复制页面下挂载的资源文件,css/js等 */ private void copyPageResources(PortalStructure sourcePortal, PortalStructure targetPortal, String supplement){ if(supplement == null) return; File dir = sourcePortal.getPortalResourceFileDir(); if( dir.exists() ) { Document doc = XMLDocUtil.dataXml2Doc(supplement); String script = doc.selectSingleNode("//page/script/file").getText(); String style = doc.selectSingleNode("//page/style/file").getText(); List<String> files = new ArrayList<String>(); files.addAll(Arrays.asList(script.split(","))); files.addAll(Arrays.asList(style.split(","))); File newDir = targetPortal.getPortalResourceFileDir(); for( String jsCssFile : files ){ File file = new File(dir.getPath() + "/" + jsCssFile); if(file.isFile()) { FileHelper.copyFile(newDir, file); } } } } // * ************************************************************************************************************************ // * *************************** 以下为门户结构"复制、复制到"操作 ************************************************************* // * ************************************************************************************************************************ public List<PortalStructure> copyTo(Long id, Long targetId, Long targetPortalId){ PortalStructure sourceNode = portalDao.getEntity(id); PortalStructure targetNode = portalDao.getEntity(targetId); if( !sourceNode.isPortletInstanse() ) { // 复制到可见的节点 List<PortalStructure> children = portalDao.getChildrenById(id, PortalConstants.PORTAL_VIEW_OPERRATION); children.remove(sourceNode); sourceNode.compose(children); } portalDao.evict(sourceNode); // 是否跨门户复制 Long sourcePortalId = sourceNode.getPortalId(); boolean isAcrossPortal = targetPortalId.equals(sourcePortalId); if( isAcrossPortal ) { sourceNode.setPortalId(targetPortalId); } //如果目标节点和原父节点是同一个,则当"复制"操作处理,name前面加前缀 if(sourceNode.getParentId().equals(targetId)) { sourceNode.setName(PortalConstants.COPY_PREFIX + sourceNode.getName()); } sourceNode.setParentId(targetId); List<PortalStructure> returnList = new ArrayList<PortalStructure>(); boolean isTargetDisableed = PortalConstants.TRUE.equals(targetNode.getDisabled()); // 目标父节点是否为停用状态 copyNodeOneByOne(sourceNode, returnList, isAcrossPortal, isTargetDisableed); if( isAcrossPortal && sourceNode.isPage() ) { PortalStructure sourcePortalNode = portalDao.getRootPortalStructure(sourcePortalId); PortalStructure targetPortalNode = portalDao.getRootPortalStructure(targetPortalId); copyPageResources(sourcePortalNode, targetPortalNode, sourceNode.getSupplement()); } return returnList; } /** * 执行逐个复制到 * @param sourcePs * @param returnList * @param isAcrossPortal * 是否跨门户复制到 * @param isTargetDisableed * 目标父节点是否为停用状态 */ private void copyNodeOneByOne(PortalStructure sourcePs, List<PortalStructure> returnList, boolean isAcrossPortal, boolean isTargetDisableed) { Long sourceId = sourcePs.getId(); // 复制源的ID sourcePs.setId(null); sourcePs.setCode(null); if(isTargetDisableed) { sourcePs.setDisabled(PortalConstants.TRUE); } PortalStructure newPs = savePortalStructure(sourcePs); Long targetPortalId = newPs.getPortalId(); //如果是复制到同一门户下的其他节点,则需要将主题信息一块复制出来。跨门户复制则不需要。 if( !isAcrossPortal ) { List<?> themes = portalDao.getThemesByPortal(targetPortalId); for( Object temp : themes ){ Theme theme = (Theme) temp; ThemeInfoId themeInfoId = new ThemeInfoId(theme.getId(), sourceId); ThemeInfo info = (ThemeInfo) portalDao.getEntity(ThemeInfo.class, themeInfoId); if(info != null){ portalDao.evict(info); info.getId().setPortalStructureId(newPs.getId()); portalDao.createObject(info); } } } returnList.add(newPs); for( PortalStructure child : sourcePs.getChildren()){ portalDao.evict(child); child.setPortalId(targetPortalId); child.setParentId(newPs.getId()); copyNodeOneByOne(child, returnList, isAcrossPortal, isTargetDisableed); } } //* ********************************************************************************************************************* //* ******************************* 以下为门户复制操作(复制整个门户) *********************************************** //* ********************************************************************************************************************* public List<PortalStructure> copyPortal(Long rootId) { PortalStructure rootps = portalDao.getEntity(rootId); if( !rootps.isRootPortal() ) { throw new BusinessException("选中节点非门户根节点,不能进行门户复制。"); } // 复制门户根节点 ------------------------------------------------------- Long portalId = rootps.getPortalId(); Portal portal = portalDao.getPortalById(portalId); portalDao.evict(portal); portal.setId(null); Portal newPortal = (Portal) portalDao.createObject(portal); PortalStructure newRootps = new PortalStructure(); BeanUtil.copy(newRootps, rootps); newRootps.setId(null); newRootps.setName(PortalConstants.COPY_PREFIX + rootps.getName()); newRootps.setPortalId(newPortal.getId()); newRootps = savePortalStructure(newRootps); // 复制门户下所有的主题(此时还没开始复制主题明细) ---------------------------- List<?> themes = portalDao.getThemesByPortal(portalId); for( Object temp : themes ) { Theme theme = (Theme) temp; Long sourceThemeId = theme.getId(); portalDao.evict(theme); theme.setId(null); theme.setPortalId(newPortal.getId()); Theme newTheme = (Theme) portalDao.createObject(theme); // 如果该主题是原先门户的默认主题,则复制出来的主题设为新门户的默认主题 if(sourceThemeId.equals(newPortal.getThemeId())){ newPortal.setThemeId(newTheme.getId()); // 默认主题 } if(sourceThemeId.equals(newPortal.getCurrentThemeId())){ newPortal.setCurrentThemeId(newTheme.getId()); // 当前主题 } } portalDao.update(newPortal); // 复制菜单 ------------------------------------------------------------- List<Navigator> menus = menuDao.getMenusByPortal(portalId); newRootps.composeMenus(menus); for( Navigator menu : newRootps.getMenus() ){ // 新复制出来的菜单根节点的seqNo需要重新生成,菜单项则不需要,照旧。 menu.setParentId(newRootps.getId()); Integer nextSeqNo = portalDao.getNextSeqNo(menu.getParentId()); menu.setSeqNo(nextSeqNo); copyMenuOneByOne(newRootps.getPortalId(), menu); } List<PortalStructure> returnList = new ArrayList<PortalStructure>(); returnList.add(newRootps); // 复制可见的子节点; List<PortalStructure> children = portalDao.getChildrenById(rootId, PortalConstants.PORTAL_VIEW_OPERRATION); children.remove(rootps); rootps.compose(children); for( PortalStructure page : rootps.getChildren() ) { // 从页面开始 copyNodeOneByOne(page, newRootps, returnList, portalId); } // 复制门户外挂资源文件 File sourceDir = PortalStructure.getPortalResourceFileDir(rootps.getCode(), portalId); if( sourceDir.exists() ) { File targetDir = newRootps.getPortalResourceFileDir(); FileHelper.copyFolder(sourceDir, targetDir); } return returnList; } private void copyNodeOneByOne(PortalStructure sourceNode, PortalStructure newParent, List<PortalStructure> returnList, Long sourcePortalId) { Long sourceId = sourceNode.getId(); portalDao.evict(sourceNode); sourceNode.setId(null); sourceNode.setCode(null); sourceNode.setPortalId(newParent.getPortalId()); sourceNode.setParentId(newParent.getId()); log.info(sourceNode); PortalStructure newps = savePortalStructure(sourceNode); log.info(newps); /* * 复制主题信息, 分主题复制。 * 在复制门户根节点的时候,已经把源门户下的所有主题都复制了一份, * 这里要做的就是把这些新复制出来的主题信息【ThemeInfo】的portalStructureId、themeId换成新门户下的对应值 */ List<?> oldThemes = portalDao.getThemesByPortal(sourcePortalId); List<?> newThemes = portalDao.getThemesByPortal(newps.getPortalId()); //themes与newThemes需要保证一一对应(复制主题的时候); for(int i = 0; i < oldThemes.size(); i++){ Theme oldTheme = (Theme) oldThemes.get(i); ThemeInfoId tiId = new ThemeInfoId(oldTheme.getId(), sourceId); ThemeInfo themeInfo = (ThemeInfo) portalDao.getEntity(ThemeInfo.class, tiId); if(themeInfo != null && newThemes != null) { Theme newTheme = (Theme) newThemes.get(i); portalDao.evict(themeInfo); themeInfo.getId().setPortalStructureId(newps.getId()); themeInfo.getId().setThemeId(newTheme.getId()); portalDao.createObject(themeInfo); } } // 修复复制出来的菜单项中关于引用到门户结构的一些地方 String hql = "from Navigator o where o.portalId = ? and "; List<?> menus = portalDao.getEntities(hql + " o.targetId = ?", newps.getPortalId(), sourceId); for( Object temp : menus ){ Navigator menu = (Navigator) temp; menu.setTargetId(newps.getId()); menuDao.updateWithoutFlush(menu); } menus = portalDao.getEntities(hql + " o.contentId = ?", newps.getPortalId(), sourceId); for( Object temp : menus ){ Navigator menu = (Navigator) temp; menu.setContentId(newps.getId()); menuDao.updateWithoutFlush(menu); } menuDao.flush(); returnList.add(newps); for( PortalStructure child : sourceNode.getChildren() ) { copyNodeOneByOne(child, newps, returnList, sourcePortalId); } } private void copyMenuOneByOne(Long newPortalId, Navigator menu){ menuDao.evict(menu); menu.setId(null); menu.setPortalId(newPortalId); Navigator newMenu = menuDao.saveMenu(menu); // 此处dao调用会被拦截进行菜单资源权限补齐 for( Navigator child : menu.getChildren() ){ child.setParentId(newMenu.getId()); copyMenuOneByOne(newPortalId, child); } } }