/*
* Copyright 2004-2012 the Seasar Foundation and the Others.
*
* 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 org.seasar.mayaa.impl.engine;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.collections.map.AbstractReferenceMap;
import org.apache.commons.collections.map.ReferenceMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.seasar.mayaa.cycle.script.CompiledScript;
import org.seasar.mayaa.engine.Engine;
import org.seasar.mayaa.engine.Page;
import org.seasar.mayaa.engine.Template;
import org.seasar.mayaa.engine.processor.ProcessStatus;
import org.seasar.mayaa.engine.processor.TemplateProcessor;
import org.seasar.mayaa.impl.cycle.CycleUtil;
import org.seasar.mayaa.impl.cycle.script.ScriptUtil;
import org.seasar.mayaa.impl.engine.specification.SpecificationImpl;
import org.seasar.mayaa.impl.engine.specification.SpecificationUtil;
import org.seasar.mayaa.impl.provider.ProviderUtil;
import org.seasar.mayaa.impl.util.StringUtil;
/**
* @author Masataka Kurihara (Gluegent, Inc)
*/
public class PageImpl extends SpecificationImpl implements Page {
private static final long serialVersionUID = -7151911061582725013L;
static final Log LOG = LogFactory.getLog(PageImpl.class);
private static final String CURRENT_PAGE_KEY = "__currentPage__";
private static final String CURRENT_COMPONENT_KEY = "__currentComponent__";
private String _pageName;
private transient Page _superPage;
private transient String _superSuffix;
private transient String _superExtension;
private transient Map _beginRenderListeners;
private String _suffixScriptText;
private CompiledScript _suffixScript;
public void initialize(String pageName) {
if (StringUtil.isEmpty(pageName)) {
throw new IllegalArgumentException();
}
if (pageName.charAt(0) != '/') {
pageName = "/" + pageName;
}
_pageName = pageName;
}
protected void prepareSuper() {
if (_superPage != null && _superPage.isDeprecated() == false) {
return;
}
synchronized (this) {
if (_superPage != null && _superPage.isDeprecated() == false) {
return;
}
// TODO mayaa以外からも取得できるようにする
String extendsPath =
SpecificationUtil.getMayaaAttributeValue(this, QM_EXTENDS);
if (StringUtil.isEmpty(extendsPath)) {
return;
}
Engine engine = ProviderUtil.getEngine();
String suffixSeparator = engine.getParameter(SUFFIX_SEPARATOR);
String[] pagePath = StringUtil.parsePath(extendsPath, suffixSeparator);
_superPage = engine.getPage(
StringUtil.adjustRelativePath(_pageName, pagePath[0]));
_superSuffix = pagePath[1];
_superExtension = pagePath[2];
}
}
public Page getSuperPage() {
prepareSuper();
return _superPage;
}
public String getSuperSuffix() {
prepareSuper();
return _superSuffix;
}
public String getSuperExtension() {
prepareSuper();
return _superExtension;
}
public String getPageName() {
return _pageName;
}
public CompiledScript getSuffixScript() {
String value = SpecificationUtil.getMayaaAttributeValue(
this, QM_TEMPLATE_SUFFIX);
if (StringUtil.isEmpty(value)) {
value = SpecificationUtil.getMayaaAttributeValue(
ProviderUtil.getEngine(), QM_TEMPLATE_SUFFIX);
}
if (StringUtil.isEmpty(value)) {
value = "";
}
if (_suffixScript != null && value.equals(_suffixScriptText)) {
return _suffixScript;
}
_suffixScript = ScriptUtil.compile(value, String.class);
_suffixScriptText = value;
return _suffixScript;
}
protected Template findTemplateFromCache(String systemID) {
Engine engine = ProviderUtil.getEngine();
return (Template) engine.findSpecificationFromCache(systemID);
}
protected Template getTemplateFromFixedSuffix(
String suffix, String extension) {
if (suffix == null || extension == null) {
throw new IllegalArgumentException();
}
Engine engine = ProviderUtil.getEngine();
synchronized (engine) {
String systemID = engine.getTemplateID(this, suffix, extension);
Template template = findTemplateFromCache(systemID);
if (template != null) {
if (template.getSource().exists()) {
return template;
}
return null;
}
return engine.createTemplateInstance(this, suffix, extension);
}
}
public Template getTemplate(String suffix, String extension) {
if (suffix == null) {
suffix = "";
}
if (extension == null) {
extension = "";
}
if (EngineUtil.getMayaaExtensionName().equals(extension)) {
return null;
}
Template template = getTemplateFromFixedSuffix(suffix, extension);
if (template == null && StringUtil.hasValue(suffix)) {
template = getTemplateFromFixedSuffix("", extension);
}
if (template == null) {
throw new PageNotFoundException(_pageName, extension);
}
return template;
}
public ProcessStatus doPageRender(
String requestedSuffix, String extension) {
Page prevPage = getCurrentPage();
setCurrentPage(this);
Engine engine = ProviderUtil.getEngine();
SpecificationUtil.execEvent(engine, QM_BEFORE_RENDER_PAGE);
try {
Page component = this;
Page superPage = component.getSuperPage();
if (superPage != null) {
component = superPage;
}
Page prevComponent = getCurrentComponent();
setCurrentComponent(component);
SpecificationUtil.execEvent(engine, QM_BEFORE_RENDER_COMPONENT);
try {
notifyBeginRender();
return RenderUtil.renderPage(true, this, null,
this, requestedSuffix, extension);
} finally {
setCurrentComponent(component);
try {
SpecificationUtil.execEvent(engine, QM_AFTER_RENDER_COMPONENT);
} finally {
setCurrentComponent(prevComponent);
}
}
} finally {
setCurrentPage(this);
try {
SpecificationUtil.execEvent(engine, QM_AFTER_RENDER_PAGE);
} finally {
setCurrentPage(prevPage);
}
}
}
protected static Page getCurrentPage() {
return (Page)CycleUtil.getRequestScope().getAttribute(CURRENT_PAGE_KEY);
}
protected static void setCurrentPage(Page page) {
CycleUtil.getRequestScope().setAttribute(CURRENT_PAGE_KEY, page);
}
public static Page getCurrentComponent() {
return (Page)CycleUtil.getRequestScope().getAttribute(CURRENT_COMPONENT_KEY);
}
public static void setCurrentComponent(Page component) {
CycleUtil.getRequestScope().setAttribute(CURRENT_COMPONENT_KEY, component);
}
// for serialize
private void readObject(java.io.ObjectInputStream in)
throws java.io.IOException, ClassNotFoundException {
in.defaultReadObject();
}
// TemplateRenderer implements ----------------------------------
public ProcessStatus renderTemplate(
Page topLevelPage, Template[] templates) {
if (topLevelPage == null || templates == null
|| templates.length == 0) {
throw new IllegalArgumentException();
}
return templates[0].doTemplateRender(topLevelPage);
}
protected Map getBeginRenderListeners() {
synchronized(this) {
if (_beginRenderListeners == null) {
_beginRenderListeners = new ReferenceMap(
AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true);
}
}
return _beginRenderListeners;
}
public boolean registBeginRenderNotifier(TemplateProcessor processor) {
boolean result =
getBeginRenderListeners().containsKey(processor) == false;
if (result == false) {
getBeginRenderListeners().put(processor, Boolean.TRUE);
}
return result;
}
protected void notifyBeginRender() {
for (Iterator it = getBeginRenderListeners().keySet().iterator();
it.hasNext(); ) {
TemplateProcessor listener = (TemplateProcessor) it.next();
listener.notifyBeginRender(this);
}
}
}