package com.aggrepoint.winlet.site.domain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
import com.aggrepoint.utils.TwoValues;
import com.aggrepoint.winlet.AuthorizationEngine;
import com.aggrepoint.winlet.ContextUtils;
import com.aggrepoint.winlet.PsnRuleEngine;
/**
*
* @author Jiangming Yang (yangjm@gmail.com)
*/
public class Page extends Base {
static final Log logger = LogFactory.getLog(Page.class);
private Branch branch;
private String path;
private String template;
private Hashtable<String, String> templatePrefixes;
private String link;
private String title;
private boolean skip;
private boolean hide;
private boolean expand;
/** 扩展访问规则 */
private String expandRule;
private boolean isStatic;
private List<Area> areas = new ArrayList<Area>();
private Hashtable<String, List<Area>> areasByName = new Hashtable<String, List<Area>>();
private List<Page> pages = new ArrayList<Page>();
private Page parent;
private int level;
private String fullPath;
private String fullDir;
private Set<String> expandAreas = new HashSet<String>();
/** key为area name,twovalues中第一个值为规则,第二个值为如果符合规则要映射到的area name */
private Map<String, List<TwoValues<String, String>>> areaMap = new HashMap<String, List<TwoValues<String, String>>>();
protected HashMap<String, String> data;
public void init(Page p, List<Area> cascade, String tmpl,
Hashtable<String, String> prefix) {
Collections.sort(pages);
branch = p.branch;
parent = p;
level = p.getLevel() + 1;
fullPath = p.fullPath + path + "/";
fullDir = p.fullDir + dir + "/";
if (cascade != null)
areas.addAll(cascade);
Collections.sort(areas);
ArrayList<Area> c2 = new ArrayList<Area>();
for (Area area : areas)
if (area.isCascade())
c2.add(area);
if (template == null)
template = tmpl;
if (templatePrefixes == null)
templatePrefixes = prefix;
areasByName.clear();
for (Area area : areas) {
List<Area> list = areasByName.get(area.getName());
if (list == null) {
list = new ArrayList<Area>();
areasByName.put(area.getName(), list);
}
list.add(area);
}
for (Page pg : pages)
pg.init(this, c2, template, templatePrefixes);
}
public Branch getBranch() {
return branch;
}
public void setBranch(Branch branch) {
this.branch = branch;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
this.fullPath = path;
}
@Override
public void setDir(String dir) {
this.dir = dir;
this.fullDir = dir;
}
public String getPsnTemplate(PsnRuleEngine psnEngine) throws Exception {
if (templatePrefixes == null)
return template;
for (String rule : templatePrefixes.keySet())
if (psnEngine.eval(rule))
return templatePrefixes.get(rule) + template;
logger.warn("No matching tempalte prefix found for page" + fullPath
+ ", use default template.");
return template;
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
public Hashtable<String, String> getTemplatePrefixes() {
return templatePrefixes;
}
public void setTemplatePrefixes(Hashtable<String, String> templatePrefixes) {
this.templatePrefixes = templatePrefixes;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isSkip() {
return skip;
}
public void setSkip(boolean skip) {
this.skip = skip;
}
public boolean isHide() {
return hide;
}
public void setHide(boolean hide) {
this.hide = hide;
}
public boolean isExpand() {
return expand;
}
public void setExpand(boolean expand) {
this.expand = expand;
}
public String getExpandRule() {
return expandRule;
}
public void setExpandRule(String expandRule) {
this.expandRule = expandRule;
}
public boolean isStatic() {
return isStatic;
}
public void setStatic(boolean isStatic) {
this.isStatic = isStatic;
if (this.isStatic)
expand = true;
}
public List<Area> getAreas(String name) {
List<TwoValues<String, String>> list = areaMap.get(name);
if (list != null) {
PsnRuleEngine engine = ContextUtils.getPsnRuleEngine(ContextUtils
.getRequest());
for (TwoValues<String, String> map : list)
try {
if (engine.eval(map.getOne())) {
name = map.getTwo();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return areasByName.get(name);
}
public List<Area> getAreas() {
return areas;
}
public List<Area> getAreas(boolean expand) {
return areas.stream().filter(p -> {
boolean isExpand = expandAreas.contains(p.getName());
return expand && isExpand || !expand && !isExpand;
}).collect(Collectors.toList());
}
public void addAreaMap(String from, String to, String rule) {
List<TwoValues<String, String>> list = areaMap.get(from);
if (list == null) {
list = new ArrayList<TwoValues<String, String>>();
areaMap.put(from, list);
}
list.add(new TwoValues<String, String>(rule, to));
}
public void addArea(Area area) {
areas.add(area);
}
protected List<Page> getPages() {
return pages;
}
protected boolean containsNotSkip(AuthorizationEngine ap) {
if (!skip)
return true;
for (Page page : pages)
if (ap.check(page, false) == null)
if (page.containsNotSkip(ap))
return true;
return false;
}
public List<Page> getPages(AuthorizationEngine ap, boolean includeHide,
boolean constainsNotSkip, boolean includeExpand) {
if (pages.size() == 0)
return pages;
List<Page> list = new ArrayList<Page>();
for (Page p : pages) {
if (!includeHide && p.isHide())
continue;
try {
if (ap.check(p, false) == null || includeExpand && p.isExpand()
&& ap.check(p, true) == null)
if (!constainsNotSkip || p.containsNotSkip(ap))
list.add(p);
} catch (Exception e) {
logger.error("Error evaluating rule \"" + p.getRule()
+ "\" or \"" + p.getExpandRule()
+ "\" defined on page \"" + p.getFullPath() + "\".", e);
}
}
return list;
}
public void addPage(Page page) {
pages.add(page);
}
public Page getParent() {
return parent;
}
public int getLevel() {
return level;
}
public String getFullPath() {
return fullPath;
}
public String getFullDir() {
return fullDir;
}
public Page findPage(String path, AuthorizationEngine ap) {
if (path.equals(fullPath)) {
// 非扩展匹配,确认符合非扩展匹配规则
// getPage()返回的页面有可能是符合扩展匹配但不符合非扩展匹配,所以需要检查
try {
if (ap.check(this, false) == null)
return this;
} catch (Exception e) {
logger.error("Error evaluating rule \"" + rule
+ "\" defined on page \"" + getFullPath() + "\".", e);
}
return null;
}
if (!path.startsWith(fullPath))
return null;
List<Page> list = getPages(ap, true, true, true);
for (Page p : list) {
Page f = p.findPage(path, ap);
if (f != null)
return f;
}
if (isExpand())
try {
if (ap.check(this, true) == null) {
// 扩展匹配,确认符合扩展匹配规则
// getPage()返回的页面有可能是符合非扩展匹配但不符合扩展匹配,所以需要检查
return this;
}
} catch (Exception e) {
logger.error("Error evaluating rule \"" + expandRule
+ "\" defined on page \"" + getFullPath() + "\".", e);
}
return null;
}
public Page findNotSkip(AuthorizationEngine ap) {
if (!skip)
return this;
List<Page> list = getPages(ap, true, true, false);
if (list.size() == 0)
return this;
return list.get(0).findNotSkip(ap);
}
public HashMap<String, String> getDataMap() {
if (data == null)
data = new HashMap<String, String>();
return data;
}
public void addData(String name, String value) {
getDataMap().put(name, value);
}
public String getData(String name) {
return getDataMap().get(name);
}
public void setExpandAreas(String expandAreas) {
if (StringUtils.isEmpty(expandAreas))
return;
StringTokenizer st = new StringTokenizer(expandAreas, " ,;");
while (st.hasMoreTokens())
this.expandAreas.add(st.nextToken());
}
public boolean isExpandArea(String name) {
return expandAreas.contains(name);
}
}