package com.ninedemons.aemtesting.models.title;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.day.cq.wcm.api.designer.Style;
import com.day.cq.wcm.commons.WCMUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.models.annotations.Via;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.HashMap;
import java.util.Map;
/**
* A model for the Title component.
*
* This is a drop in replacement for the auto-generated title.js javascript model the maven archetype creates.
*/
@Model(adaptables = SlingHttpServletRequest.class)
public class TitleModel {
private static final Logger LOG = LoggerFactory.getLogger(TitleModel.class);
/** TODO This model has knowledge about the HTML elements to use when rendering the title. This violates separation
* of concerns between a model and the rendering layer. This part of the model should be embedded in the sightly
* markup, not here.
*/
/**
* The default HTML element to use when none explicitly set
*/
private static final String DEFAULT_ELEMENT = "h2";
/**
* Holds the mappings of the type of the title to the actual HTML element to use
*/
private final static Map<String,String> TYPE_TO_ELEMENT;
static {
TYPE_TO_ELEMENT = new HashMap<String, String>(2);
TYPE_TO_ELEMENT.put("small", "h3");
TYPE_TO_ELEMENT.put("extralarge", "h1");
}
@Optional
@Inject @Via("resource") @Named(JcrConstants.JCR_TITLE)
private String componentTitle;
@Optional
@Inject @Via("resource")
private String type;
/**
* The text for use in the title
*/
private String text;
/**
* The HTML element that the title text will be wrapped in
*/
private String element;
private SlingHttpServletRequest request;
public TitleModel(SlingHttpServletRequest request) {
this.request = request;
}
public String getText() {
return text;
}
public String getElement() {
return element;
}
@PostConstruct
private void setup() {
findCurrentStyle();
findContainingPage();
findText();
findElement();
}
private Style findCurrentStyle() {
return WCMUtils.getStyle(request);
}
private Page findContainingPage() {
final Resource resource = request.getResource();
final ResourceResolver resourceResolver = resource.getResourceResolver();
final PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
return pageManager.getContainingPage(resource);
}
private void findText() {
LOG.trace("Finding text to use");
LOG.trace("Considering the component jcr:text property");
text = componentTitle;
if (StringUtils.isBlank(text)) {
Page containingPage = findContainingPage();
LOG.trace("Considering the text of the current page");
text = containingPage.getTitle();
if (StringUtils.isBlank(text)) {
LOG.trace("Defaulting to the name of the current page");
text = containingPage.getName();
}
}
LOG.trace("Text for the title is '{}'",text);
}
private void findElement() {
String type = findType();
element = MapUtils.getString(TYPE_TO_ELEMENT,type,DEFAULT_ELEMENT);
LOG.trace("HTML element for the title is '{}'",element);
}
private String findType() {
LOG.trace("Finding type to use");
LOG.trace("Considering the component type property");
String type = this.type;
if (StringUtils.isBlank(type)) {
LOG.trace("Defaulting to Design default type");
findCurrentStyle().get("defaultType",StringUtils.EMPTY);
}
return type;
}
}