/**
* Copyright 2013 the original author or authors.
*
* 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 io.neba.api.tags;
import io.neba.api.resourcemodels.ResourceModelProvider;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScriptHelper;
import tldgen.Tag;
import tldgen.TagAttribute;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import static io.neba.api.Constants.MODEL;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.apache.sling.api.scripting.SlingBindings.SLING;
/**
* @author Olaf Otto
*/
@Tag(description = "Adds the most specific @ResourceModel" +
" for the current resource under the key \"m\", if such a model exists.")
public final class DefineObjectsTag extends TagSupport {
private static final long serialVersionUID = 3746304163438347809L;
private boolean includeGenericBaseTypes = false;
private String modelBeanName;
@Override
public int doEndTag() throws JspException {
provideMostSpecificResourceModel();
return EVAL_PAGE;
}
@TagAttribute(description = "Whether to include models mapping to " +
"generic base types such as \"nt:unstructured\" or " +
"\"nt:base\". Defaults to false. Has no effect if a " +
"modelName is provided.",
required = false, runtimeValueAllowed = true)
public void setIncludeGenericBaseTypes(boolean includeGenericBaseTypes) {
this.includeGenericBaseTypes = includeGenericBaseTypes;
}
@TagAttribute(description = "The explicit bean name of the resource model that shall " +
"be provided for the resource. The targeted resource model must still be " +
"declared for a resource type compatible with the resource's type. The searched " +
"models will always include generic base models, regardless of whether " +
"includeGenericBaseTypes is false.",
required = false, runtimeValueAllowed = true)
public void setUseModelNamed(String name) {
this.modelBeanName = name;
}
private void provideMostSpecificResourceModel() {
SlingScriptHelper scriptHelper = getScriptHelper();
ResourceModelProvider modelProvider = scriptHelper.getService(ResourceModelProvider.class);
if (modelProvider == null) {
// Can be the case if called before / after provider lifetime, e.g.
// when the application context is stopped. Fail fast.
throw new IllegalStateException("The " + ResourceModelProvider.class.getSimpleName() + " must not be null." +
" Is this tag used while the NEBA core is not started?");
}
Resource resource = getResource();
Object model;
if (!isBlank(this.modelBeanName)) {
model = modelProvider.resolveMostSpecificModelWithBeanName(resource, this.modelBeanName);
} else if (this.includeGenericBaseTypes) {
model = modelProvider.resolveMostSpecificModelIncludingModelsForBaseTypes(resource);
} else {
model = modelProvider.resolveMostSpecificModel(resource);
}
if (model != null) {
this.pageContext.setAttribute(MODEL, model);
}
}
private Resource getResource() {
SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) this.pageContext.getRequest();
return slingRequest.getResource();
}
protected SlingBindings getBindings() {
return (SlingBindings) this.pageContext.getRequest().getAttribute(SlingBindings.class.getName());
}
protected SlingScriptHelper getScriptHelper() {
SlingBindings bindings = getBindings();
if (bindings == null) {
throw new IllegalStateException("No " + SlingBindings.class.getName() +
" was found in the request, got null.");
}
SlingScriptHelper scriptHelper = (SlingScriptHelper) bindings.get(SLING);
if (scriptHelper == null) {
throw new IllegalStateException("No " + SlingScriptHelper.class.getName() +
" was found in the sling bindings, got null.");
}
return scriptHelper;
}
}