/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.citrus.service.mail.builder.content;
import static com.alibaba.citrus.service.mail.MailConstant.*;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static com.alibaba.citrus.util.ObjectUtil.*;
import static com.alibaba.citrus.util.StringUtil.*;
import java.io.IOException;
import java.util.Set;
import com.alibaba.citrus.service.mail.builder.MailBuilder;
import com.alibaba.citrus.service.mail.builder.MailBuilderException;
import com.alibaba.citrus.service.pull.PullContext;
import com.alibaba.citrus.service.pull.PullService;
import com.alibaba.citrus.service.template.TemplateContext;
import com.alibaba.citrus.service.template.TemplateException;
import com.alibaba.citrus.service.template.TemplateService;
import com.alibaba.citrus.util.ToStringBuilder.MapBuilder;
/**
* 从模板生成的内容。
*
* @author Michael Zhou
*/
public abstract class TemplateContent extends AbstractContent {
private TemplateService templateService;
private PullService pullService;
private String templateName;
private String contentType;
private transient TemplateContext templateContext;
/** 取得template服务。 */
public TemplateService getTemplateService() {
return assertNotNull(getService(TemplateService.class, "templateService", templateService), "templateService");
}
/** 设置template服务。 */
public void setTemplateService(TemplateService templateService) {
this.templateService = templateService;
}
/** 取得pull服务。 */
public PullService getPullService() {
return getService(PullService.class, "pullService", pullService);
}
/** 设置pull服务。 */
public void setPullService(PullService pullService) {
this.pullService = pullService;
}
/** 取得模板的名称。 */
public String getTemplateName() {
return templateName;
}
/** 设置模板的名称。 */
public void setTemplate(String templateName) {
this.templateName = trimToNull(templateName);
}
/** 取得文本的content type。 */
public String getContentType() {
return defaultIfNull(contentType, getDefaultContentType());
}
protected String getDefaultContentType() {
return CONTENT_TYPE_TEXT_PLAIN;
}
/** 设置文本的content type。 */
public void setContentType(String contentType) {
this.contentType = trimToNull(contentType);
}
/** 渲染模板。 */
protected final String renderTemplate() throws MailBuilderException {
try {
return getTemplateService().getText(templateName, getTemplateContext());
} catch (TemplateException e) {
throw new MailBuilderException("Failed to render template: " + templateName, e);
} catch (IOException e) {
throw new MailBuilderException("Failed to render template: " + templateName, e);
}
}
/** 取得template context。 */
private TemplateContext getTemplateContext() {
if (templateContext == null) {
PullService pullService = getPullService();
PullContext pullContext = null;
if (pullService != null) {
pullContext = pullService.getContext();
}
templateContext = new TemplateContextAdapter(getMailBuilder(), pullContext);
populateTemplateContext(templateContext);
}
return templateContext;
}
/** 给子类一个机会来初始化context。 */
protected void populateTemplateContext(TemplateContext templateContext) {
}
/** 深度复制一个content。 */
@Override
protected void copyTo(AbstractContent copy) {
TemplateContent copyContent = (TemplateContent) copy;
copyContent.templateService = templateService;
copyContent.pullService = pullService;
copyContent.templateName = templateName;
copyContent.contentType = contentType;
}
@Override
protected void toString(MapBuilder mb) {
mb.append("contentType", getContentType());
mb.append("templateName", templateName);
}
/** 将mail builder适配到<code>TemplateContext</code>。 */
private static class TemplateContextAdapter implements TemplateContext {
private final MailBuilder builder;
private final PullContext pullContext;
public TemplateContextAdapter(MailBuilder builder, PullContext pullContext) {
this.builder = assertNotNull(builder, "mailBuilder");
this.pullContext = pullContext;
}
public boolean containsKey(String key) {
return builder.getAttribute(key) != null || pull(key) != null;
}
public Object get(String key) {
Object object = builder.getAttribute(key);
if (object == null) {
return pull(key);
} else {
return object;
}
}
public Set<String> keySet() {
if (pullContext == null) {
return builder.getAttributeKeys();
} else {
Set<String> keys = createHashSet(builder.getAttributeKeys());
keys.addAll(pullContext.getToolNames());
return keys;
}
}
public void put(String key, Object value) {
builder.setAttribute(key, value);
}
public void remove(String key) {
builder.setAttribute(key, null);
}
private Object pull(String key) {
if (pullContext != null) {
return pullContext.pull(key);
} else {
return null;
}
}
@Override
public String toString() {
MapBuilder mb = new MapBuilder().setSortKeys(true).setPrintCount(true);
for (String key : builder.getAttributeKeys()) {
mb.append(key, builder.getAttribute(key));
}
return mb.toString();
}
}
}