/* ================================================================== * 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.action; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import com.jinhe.tss.core.cachepool.CacheManager; import com.jinhe.tss.core.cachepool.DefaultCacheableKey; import com.jinhe.tss.core.cachepool.IPool; import com.jinhe.tss.core.sso.Environment; import com.jinhe.tss.core.util.EasyUtils; import com.jinhe.tss.core.util.XMLDocUtil; import com.jinhe.tss.core.web.dispaly.grid.DefaultGridNode; import com.jinhe.tss.core.web.dispaly.grid.GridDataEncoder; import com.jinhe.tss.core.web.dispaly.grid.IGridNode; import com.jinhe.tss.core.web.dispaly.tree.ILevelTreeNode; import com.jinhe.tss.core.web.dispaly.tree.ITreeTranslator; import com.jinhe.tss.core.web.dispaly.tree.LevelTreeParser; import com.jinhe.tss.core.web.dispaly.tree.TreeEncoder; import com.jinhe.tss.core.web.dispaly.tree.TreeNode; import com.jinhe.tss.core.web.dispaly.xform.XFormEncoder; import com.jinhe.tss.portal.PortalConstants; import com.jinhe.tss.portal.engine.FreeMarkerSupportAction; import com.jinhe.tss.portal.engine.HTMLGenerator; import com.jinhe.tss.portal.engine.model.PortalNode; import com.jinhe.tss.portal.engine.releasehtml.MagicRobot; import com.jinhe.tss.portal.engine.releasehtml.SimpleRobot; import com.jinhe.tss.portal.entity.IssueInfo; import com.jinhe.tss.portal.entity.PortalStructure; import com.jinhe.tss.portal.entity.Theme; import com.jinhe.tss.portal.entity.permission.PortalResourceView; import com.jinhe.tss.portal.helper.PortalStructureWrapper; import com.jinhe.tss.portal.helper.StrictLevelTreeParser; import com.jinhe.tss.portal.service.IPortalService; import com.jinhe.tss.um.permission.PermissionHelper; import freemarker.template.TemplateException; public class PortalAction extends FreeMarkerSupportAction { private static final long serialVersionUID = -7584264166655878781L; private Long id; private Long resourceId; private String name; private Integer type; // 门户结构类型:0,1,2,3 private Long parentId; // 父节点Id,新增时用,门户结构根节点的parentId = 0 private Long themeId; private Integer disabled; private Long targetId; // 移动或者排序的目标节点ID private int direction; // +1(向下)/ -1(向上) private String code; private String method; // browse/view/maintain private PortalStructureWrapper ps = new PortalStructureWrapper(); private IssueInfo issueInfo = new IssueInfo(); private IPortalService service; /** * 预览门户 * @return */ public String previewPortal() throws IOException, TemplateException{ PortalNode portalNode = service.getPortal(portalId, themeId, method); HTMLGenerator gen = new HTMLGenerator(portalNode, id, getFreemarkerParser()); return printHTML(gen.toHTML(), false); } /** * 获取页面上某个版面或者portletInstanse的xml格式内容。 * 用以替换某块指定的区域(targetId对应的版面(或页面)中布局器的替换区域:navigatorContentIndex)。 * 菜单点击的时候会调用到本方法。 * @return * @throws TemplateException * @throws IOException */ public String getPortalXML() throws IOException, TemplateException{ PortalNode portalNode = service.getPortal(portalId, themeId, method); HTMLGenerator gen = new HTMLGenerator(portalNode, id, targetId, getFreemarkerParser()); StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"GBK\"?>"); sb.append("<Response><Portlet>").append(gen.toXML()).append("</Portlet></Response>"); return printHTML(sb.toString(), false); } /** * 静态发布匿名访问的门户 * @return */ public String staticIssuePortal(){ if(type.intValue() == 1){ // 发布整个站点 MagicRobot robot = new MagicRobot(id); robot.start(); String feedback = robot.getFeedback(); return printSuccessMessage(feedback); } else if(type.intValue() == 2){ // 只发布当前页 String visitUrl = service.getIssueInfo(id).getVisitUrl(); new SimpleRobot(visitUrl).start(); return printSuccessMessage("页面静态发布门户成功!"); } return XML; } /** * <p> * 获取所有的Portal对象(取门户结构PortalStructure)并转换成Tree相应的xml数据格式 * </p> * @return */ public String getAllPortals4Tree() { List<?> data = service.getAllPortalStructures(); TreeEncoder encoder = new TreeEncoder(data, new StrictLevelTreeParser()); return print("SiteTree", encoder); } public String getOperationsByResource() { PermissionHelper permissionHelper = PermissionHelper.getInstance(); resourceId = resourceId == null ? PortalConstants.ROOT_ID : resourceId; List<String> list = permissionHelper.getOperationsByResource(resourceId, "PortalPermissionsFull", PortalResourceView.class); // 加入授予角色权限 String portalResourceType = PortalConstants.PORTAL_RESOURCE_TYPE; List<?> highOperations = permissionHelper.getHighOperationsByResource( portalResourceType, resourceId, Environment.getOperatorId() ); if( !highOperations.isEmpty() ) { list.add("_1"); } return print("Operation", "p1,p2," + EasyUtils.list2Str(list) ); } /** * <p> * 获取除portlet应用外的门户结构,并转换成Tree相应的xml数据格式。 * 应该是先取所有有新增权限的节点,再取它们可见的父节点组装成树,可见的父节点将设为不能被选择。 * 另外还要过滤掉自身节点为不可选。 * * 移动到...,复制到...的时候将调用本方法。 * </p> * @return */ @SuppressWarnings("unchecked") public String getActivePortalStructures4Tree() { List<ILevelTreeNode> all = (List<ILevelTreeNode>) service.getAllPortalStructures(); List<ILevelTreeNode> targets = (List<ILevelTreeNode>) service.getTargetPortalStructures(); final List<Long> targetIds = new ArrayList<Long>(); for( ILevelTreeNode temp : targets ){ targetIds.add( temp.getId() ); } List<ILevelTreeNode> composedTree = composeTargetTree(all, targets); TreeEncoder encoder = new TreeEncoder(composedTree, new StrictLevelTreeParser()); final int type = service.getPortalStructureById(id).getType(); encoder.setTranslator( new ITreeTranslator() { // 门户结构树转换器:门户结构移动时根据当前节点的type值过滤其它节点是否可以选择 public Map<String, Object> translate(Map<String, Object> attributes) { if( id.equals(attributes.get("id"))){ attributes.put(TreeNode.TREENODE_ATTRIBUTE_CANSELECTED, "0"); } Integer tempType = (Integer)attributes.get("type"); switch(type){ case 1: // 移动的是页面,则非门户节点的都不可选 if(PortalStructure.TYPE_PORTAL != tempType) { attributes.put(TreeNode.TREENODE_ATTRIBUTE_CANSELECTED, "0"); } break; case 2: case 3: // 移动的是版面或portlet实例,则门户节点不可选 if(PortalStructure.TYPE_PORTAL == tempType) { attributes.put(TreeNode.TREENODE_ATTRIBUTE_CANSELECTED, "0"); } break; } return attributes; } }); encoder.setRootCanSelect(false); return print("SiteTree", encoder); } /** * 将断层的节点的所有父节点补齐 * @param all * @param targets * @return */ private List<ILevelTreeNode> composeTargetTree(List<ILevelTreeNode> all, List<ILevelTreeNode> targets){ if(targets == null || targets.isEmpty()) return new ArrayList<ILevelTreeNode>(); Map<Long, ILevelTreeNode> entitiesMap = new HashMap<Long, ILevelTreeNode>(); for( ILevelTreeNode entity : all){ entitiesMap.put(entity.getId(), entity); } Map<Long, ILevelTreeNode> targetEntitiesMap = new HashMap<Long, ILevelTreeNode>(); for( ILevelTreeNode entity : targets){ targetEntitiesMap.put(entity.getId(), entity); } //此处是递归过程,targets会变大,会将断层的节点一直往上取到所有父节点 for( ILevelTreeNode entity : targets){ Long parentId = entity.getParentId(); ILevelTreeNode parent = targetEntitiesMap.get(parentId); if(parent == null && !parentId.equals(PortalConstants.ROOT_ID)){ targets.add(parent = entitiesMap.get(parentId)); } } return targets; } /** * <p> * 获取单个门户结构PortalStructure的节点信息,并转换成XForm相应的xml数据格式; * 如果该门户结构PortalStructure是根节点,则要一块取出其对应门户Portal的信息 * </p> * @return */ public String getPortalStructureInfo(){ XFormEncoder encoder; if(isCreateNew()) { // 如果是新增,则返回一个空的无数据的模板 Map<String, Object> map = new HashMap<String, Object>(); map.put("type", type); map.put("parentId", parentId); map.put("portalId", portalId); encoder = new XFormEncoder(PortalConstants.PORTALSTRUCTURE_XFORM_PATH, map); } else { PortalStructure info = service.getPoratalStructure(id); encoder = new XFormEncoder(PortalConstants.PORTALSTRUCTURE_XFORM_PATH, info); if(info.getType().equals(PortalStructure.TYPE_PORTAL)){ Object[] objs = genComboThemes(info.getPortalId()); encoder.setColumnAttribute("currentThemeId", "editorvalue", (String) objs[0]); encoder.setColumnAttribute("currentThemeId", "editortext", (String) objs[1]); encoder.setColumnAttribute("themeName", "editable", "false"); } } return print("SiteInfo", encoder); } private Object[] genComboThemes(Long portalId){ List<?> data = service.getThemesByPortal(portalId); return EasyUtils.generateComboedit(data, "id", "name", "|"); } /** * <p> * 保存门户结构信息,如果该门户结构PortalStructure是根节点,则要一块保存其门户Portal的信息。 * </p> * @return */ public String save(){ boolean isNew = (ps.getId() == null); PortalStructure portalStructure; if(isNew) { ps.setCode("PS" + System.currentTimeMillis()); // 设置code值 = PS + 当前时间 portalStructure = service.createPortalStructure(ps); /** * 如果是在新增门户根节点时上传文件,则此时code和Id还没生成。 * code值=页面随机生成的一个全局变量(注:code为本action的一个单独属性值),id="null"。<br/> * 待保存门户根节点再将名字重新根据生成 code + portalId 值命名。 */ if( ps.getType().equals(PortalStructure.TYPE_PORTAL) ) { File tempDir = PortalStructure.getPortalResourceFileDir(code + "_null"); if(tempDir.exists()) { tempDir.renameTo(portalStructure.getPortalResourceFileDir()); } } } else { portalStructure = service.updatePortalStructure(ps); } return doAfterSave(isNew, portalStructure, "SiteTree"); } /** * <p> * 删除门户结构PortalStructure * 如果有子节点,同时删除子节点(递归过程,子节点的子节点......) * </p> * @return */ public String delete(){ service.delete(id); return printSuccessMessage(); } /** * <p> * 停用/启用 门户结构PortalStructure(将其下的disabled属性设为"1"/"0") * 停用时,如果有子节点,同时停用所有子节点(递归过程,子节点的子节点......) * 启用时,如果有父节点且父节点为停用状态,则启用父节点(也是递归过程,父节点的父节点......) * </p> * @return */ public String disable(){ service.disable(id, disabled); return printSuccessMessage(); } /** * <p> * 跨父节点移动门户结构PortalStructure节点。 * 移动到弹出窗口中选中的门户结构下(一般为"门户、页面、版面"节点)。 * </p> * @return */ public String move() { service.move(id, targetId, portalId); return printSuccessMessage(); } /** * <p> * 排序,同节点下的节点排序(一次只能排一个) * </p> * @return */ public String order() { service.order(id, targetId, direction); return printSuccessMessage(); } /** * <p> * 在同一父节点下复制门户或者门户节点,要求新输入一个名字。 * </p> * @return */ public String copyPortal() { List<?> list = service.copyPortal(id); TreeEncoder encoder = new TreeEncoder(list, new LevelTreeParser()); encoder.setNeedRootNode(false); return print("SiteTree", encoder); } /** * <p> * 复制门户或者门户节点到不同的父节点下,要求新输入一个名字。 * </p> * @return */ public String copyTo() { List<?> list = service.copyTo(id, targetId, portalId); TreeEncoder encoder = new TreeEncoder(list, new LevelTreeParser()); encoder.setNeedRootNode(false); return print("SiteTree", encoder); } //******************************** 以下为主题管理 *************************************** /** * 获取一个Portal的所有主题 * @return */ public String getThemes4Tree(){ PortalStructureWrapper rootps = (PortalStructureWrapper) service.getPoratalStructure(id); List<?> themeList = service.getThemesByPortal(rootps.getPortalId()); TreeEncoder encoder = new TreeEncoder(themeList); final Long defalutThemeId = rootps.getThemeId(); encoder.setTranslator(new ITreeTranslator() { public Map<String, Object> translate(Map<String, Object> attributes) { if(defalutThemeId.equals(attributes.get("id"))){ attributes.put("isDefault", "1"); attributes.put("icon", "../platform/images/icon/default_theme.gif"); } return attributes; } }); return print("ThemeManage", encoder); } /** * <p> * 将Portal的一套主题另存为。。。 * </p> * @return */ public String saveThemeAs(){ Theme newTheme = service.saveThemeAs(themeId, name); return doAfterSave(true, newTheme, "ThemeManage"); } public String renameTheme(){ service.renameTheme(themeId, name); return printSuccessMessage(); } public String specifyDefaultTheme(){ service.specifyDefaultTheme(portalId, themeId); return printSuccessMessage(); } public String removeTheme(){ service.removeTheme(portalId, themeId); return printSuccessMessage(); } //******************************** 以下为门户发布管理 *************************************** public String getAllIssues4Tree(){ TreeEncoder encoder = new TreeEncoder(service.getAllIssues()); return print("PublishTree", encoder); } public String getIssueInfoById(){ XFormEncoder encoder = null; if( isCreateNew() ){ encoder = new XFormEncoder(PortalConstants.ISSUE_XFORM_TEMPLET_PATH); } else{ IssueInfo info = service.getIssueInfo(id); encoder = new XFormEncoder(PortalConstants.ISSUE_XFORM_TEMPLET_PATH, info); Object[] objs = genComboThemes(info.getPortalId()); encoder.setColumnAttribute("themeId", "editorvalue", (String) objs[0]); encoder.setColumnAttribute("themeId", "editortext", (String) objs[1]); } return print("PublishInfo", encoder); } public String saveIssue(){ boolean isNew = issueInfo.getId() == null ? true : false; issueInfo = service.saveIssue(issueInfo); return doAfterSave(isNew, issueInfo, "PublishTree"); } public String removeIssue(){ service.removeIssue(id); return printSuccessMessage(); } public String getActivePortals4Tree(){ List<?> data = service.getActivePortals(); TreeEncoder encoder = new TreeEncoder(data, new StrictLevelTreeParser()); encoder.setNeedRootNode(false); return print("SiteTree", encoder); } public String getThemesByPortal(){ Object[] objs = genComboThemes(portalId); String returnStr = "<column name=\"themeId\" caption=\"主题\" mode=\"string\" " + " editor=\"comboedit\" editorvalue=\"" + objs[0] + "\" editortext=\"" + objs[1] + "\"/>"; return print("ThemeList", returnStr); } public String getActivePagesByPortal4Tree(){ List<?> data = service.getActivePagesByPortal(portalId); TreeEncoder encoder = new TreeEncoder(data, new LevelTreeParser()); encoder.setNeedRootNode(false); return print("PageTree", encoder); } //******************************* 以下为门户缓存管理 *************************************** public String cacheManage(){ List<?> data = service.getThemesByPortal(portalId); StringBuffer sb= new StringBuffer("<actionSet>"); for( Object temp : data ){ Theme theme = (Theme) temp; sb.append("<cacheItem id=\"").append(theme.getId()).append("\" name=\"").append(theme.getName()).append("\" />"); } return print("CacheManage", sb.append("</actionSet>").toString()); } public String flushCache(){ IPool pool = CacheManager.getInstance().getCachePool(PortalConstants.PORTAL_TREE_CACHE); pool.removeObject(new DefaultCacheableKey(portalId + "_" + themeId)); return printSuccessMessage(); } //******************************* 获取门户流量信息 ****************************************** public String getFlowRate(){ List<?> rateItems = service.getFlowRate(portalId); List<IGridNode> gridList = new ArrayList<IGridNode>(); for(Iterator<?> it = rateItems.iterator(); it.hasNext();){ Object[] objs = (Object[]) it.next(); DefaultGridNode gridNode = new DefaultGridNode(); gridNode.getAttrs().put("name", objs[0]); gridNode.getAttrs().put("rate", objs[1]); gridList.add(gridNode); } StringBuffer template = new StringBuffer(); template.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><grid version=\"2\"><declare sequence=\"true\">"); template.append("<column name=\"name\" caption=\"页面名称\" mode=\"string\" align=\"center\"/>"); template.append("<column name=\"rate\" caption=\"访问次数\" mode=\"string\" align=\"center\"/>"); template.append("</declare><data></data></grid>"); GridDataEncoder gEncoder = new GridDataEncoder(gridList, XMLDocUtil.dataXml2Doc(template.toString())); return print("PageViewList", gEncoder); } public void setService(IPortalService service) { this.service = service; } public PortalStructureWrapper getPs() { return ps; } public void setDirection(int direction) { this.direction = direction; } public void setDisabled(Integer disabled) { this.disabled = disabled; } public void setId(Long id) { this.id = id; } public void setParentId(Long parentId) { this.parentId = parentId; } public void setTargetId(Long targetId) { this.targetId = targetId; } public void setType(Integer type) { this.type = type; } public void setName(String name) { this.name = name; } public void setCode(String code) { this.code = code; } public void setThemeId(Long themeId) { this.themeId = themeId; } public IssueInfo getIssueInfo() { return issueInfo; } public void setMethod(String method) { this.method = method; } public void setResourceId(Long resourceId) { this.resourceId = resourceId; } }