package com.astamuse.asta4d.web.dispatch.mapping.handy;
import java.util.ArrayList;
import java.util.List;
import com.astamuse.asta4d.web.dispatch.HttpMethod;
import com.astamuse.asta4d.web.dispatch.HttpMethod.ExtendHttpMethod;
import com.astamuse.asta4d.web.dispatch.mapping.UrlMappingRule;
import com.astamuse.asta4d.web.dispatch.mapping.UrlMappingRuleRewriter;
import com.astamuse.asta4d.web.dispatch.mapping.UrlMappingRuleSet;
import com.astamuse.asta4d.web.dispatch.mapping.UrlMappingRuleSetHelper;
import com.astamuse.asta4d.web.dispatch.mapping.handy.base.HandyRuleConfigurer;
import com.astamuse.asta4d.web.dispatch.mapping.handy.rest.JsonSupportRuleSet;
import com.astamuse.asta4d.web.dispatch.mapping.handy.rest.XmlSupportRuleSet;
import com.astamuse.asta4d.web.dispatch.mapping.handy.template.TemplateRuleHelper;
import com.astamuse.asta4d.web.dispatch.mapping.handy.template.TemplateRuleWithForward;
import com.astamuse.asta4d.web.dispatch.request.ResultTransformer;
import com.astamuse.asta4d.web.dispatch.request.transformer.Asta4DPageTransformer;
import com.astamuse.asta4d.web.dispatch.request.transformer.DefaultExceptionTransformer;
import com.astamuse.asta4d.web.dispatch.request.transformer.DefaultStringTransformer;
import com.astamuse.asta4d.web.dispatch.request.transformer.DefaultTemplateNotFoundExceptionTransformer;
import com.astamuse.asta4d.web.dispatch.request.transformer.SimpleTypeMatchTransformer;
@SuppressWarnings("unchecked")
public class HandyRuleSet<A extends HandyRuleAfterAddSrc<?, ?, ?>, D extends HandyRuleAfterAddSrcAndTarget<?>>
extends UrlMappingRuleSet<A, D>implements JsonSupportRuleSet, XmlSupportRuleSet, HandyRuleBuilder {
private static final String DEFAULT_RULE_TYPE = "template";
protected final static class GlobalForwardHolder {
Object result;
String targetPath;
Integer status;
boolean isRedirect;
public GlobalForwardHolder(Object result, String targetPath, Integer status, boolean isRedirect) {
super();
this.result = result;
this.targetPath = targetPath;
this.status = status;
this.isRedirect = isRedirect;
}
}
protected List<GlobalForwardHolder> forwardHolderList = new ArrayList<>();
protected UrlMappingRule createDefaultRule(HttpMethod method, ExtendHttpMethod extendMethod, String sourcePath) {
UrlMappingRule rule = new UrlMappingRule();
ruleList.add(rule);
rule.setMethod(method);
rule.setExtendMethod(extendMethod);
rule.setSourcePath(sourcePath);
rule.setSeq(Sequencer.incrementAndGet());
rule.setPriority(DEFAULT_PRIORITY);
rule.setRuleMatcher(defaultRuleMatcher);
// register the default result transformer reorganizer, can be overridden by other apis
UrlMappingRuleSetHelper.setRuleType(rule, DEFAULT_RULE_TYPE);
UrlMappingRuleSetHelper.addBeforeSortRuleRewritter(rule, new UrlMappingRuleRewriter() {
@Override
public void rewrite(UrlMappingRule rule) {
if (DEFAULT_RULE_TYPE.equals(UrlMappingRuleSetHelper.getRuleType(rule))) {
// OK
} else {
return;
}
List<ResultTransformer> transformerList = rule.getResultTransformerList();
// find out the default forward rule
ResultTransformer transformer, defaultTransformer = null;
int size = transformerList.size();
for (int i = size - 1; i >= 0; i--) {
transformer = transformerList.get(i);
if (transformer instanceof SimpleTypeMatchTransformer) {
if (((SimpleTypeMatchTransformer) transformer).isAsDefaultMatch()) {
defaultTransformer = transformer;
transformerList.remove(i);
break;
}
}
}
boolean hasHandler = !rule.getHandlerList().isEmpty();
if (hasHandler) {
// add global forward
addGlobalForwardTransformers(transformerList);
// add String transformers for non default forward rules(forward
// by result)
transformerList.add(new DefaultStringTransformer());
// add global forward again for possible
// exceptions on the above transformers
addGlobalForwardTransformers(transformerList);
// add String transformers for the global forword rules
transformerList.add(new DefaultStringTransformer());
}
// add default forward rule
if (defaultTransformer != null) {
transformerList.add(defaultTransformer);
// add default String transformers for the default forward rule
transformerList.add(new DefaultStringTransformer());
// add global forward of Throwable result again again (!!!) for
// possible exceptions on the above transformers
addGlobalForwardTransformers(transformerList);
// add String transformers for the global throwable result
// forword rules
transformerList.add(new DefaultStringTransformer());
}
// add the last insured transformers
transformerList.add(new DefaultTemplateNotFoundExceptionTransformer());
transformerList.add(new DefaultExceptionTransformer());
transformerList.add(new Asta4DPageTransformer());
}
});
return rule;
}
protected void addGlobalForwardTransformers(List<ResultTransformer> transformerList) {
for (GlobalForwardHolder forwardHolder : forwardHolderList) {
if (forwardHolder.isRedirect) {
transformerList.add(TemplateRuleHelper.redirectTransformer(forwardHolder.result, forwardHolder.targetPath));
} else if (forwardHolder.status == null) {
transformerList.add(TemplateRuleHelper.forwardTransformer(forwardHolder.result, forwardHolder.targetPath));
} else {
transformerList
.add(TemplateRuleHelper.forwardTransformer(forwardHolder.result, forwardHolder.targetPath, forwardHolder.status));
}
}
}
public void addGlobalForward(Object result, String targetPath, int status) {
forwardHolderList.add(new GlobalForwardHolder(result, targetPath, status, false));
}
public void addGlobalForward(Object result, String targetPath) {
forwardHolderList.add(new GlobalForwardHolder(result, targetPath, null, false));
}
public void addGlobalRedirect(Object result, String targetPath) {
forwardHolderList.add(new GlobalForwardHolder(result, targetPath, null, true));
}
public A add(String sourcePath) {
return add(defaultMethod, sourcePath);
}
public A add(HttpMethod method, String sourcePath) {
UrlMappingRule rule = createDefaultRule(method, null, sourcePath);
A handyRule = buildHandyRuleAfterAddSrc(rule);
return handyRule;
}
public A add(ExtendHttpMethod extendMethod, String sourcePath) {
UrlMappingRule rule = createDefaultRule(HttpMethod.UNKNOWN, extendMethod, sourcePath);
A handyRule = buildHandyRuleAfterAddSrc(rule);
return handyRule;
}
public D add(String sourcePath, String targetPath) {
return add(defaultMethod, sourcePath, targetPath);
}
public D add(HttpMethod method, String sourcePath, String targetPath) {
UrlMappingRule rule = createDefaultRule(method, null, sourcePath);
@SuppressWarnings("rawtypes")
TemplateRuleWithForward trf = new TemplateRuleWithForward() {
@Override
public void configureRule(HandyRuleConfigurer configure) {
configure.configure(rule);
}
};
trf.forward(targetPath);
return buildHandyRuleAfterAddSrcAndTarget(rule);
}
public D add(ExtendHttpMethod extendMethod, String sourcePath, String targetPath) {
UrlMappingRule rule = createDefaultRule(HttpMethod.UNKNOWN, extendMethod, sourcePath);
@SuppressWarnings("rawtypes")
TemplateRuleWithForward trf = new TemplateRuleWithForward() {
@Override
public void configureRule(HandyRuleConfigurer configure) {
configure.configure(rule);
}
};
trf.forward(targetPath);
return buildHandyRuleAfterAddSrcAndTarget(rule);
}
}