net.abstractfactory.plum.view.web.component.AbstractWebComponent Maven / Gradle / Ivy
package net.abstractfactory.plum.view.web.component;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.DigestUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import net.abstractfactory.common.ListValueMap;
import net.abstractfactory.common.TreeNode;
import net.abstractfactory.plum.input.value.File;
import net.abstractfactory.plum.view.component.Button;
import net.abstractfactory.plum.view.component.Component;
import net.abstractfactory.plum.view.component.attribute.Border;
import net.abstractfactory.plum.view.component.attribute.BorderDirection;
import net.abstractfactory.plum.view.component.attribute.Length;
import net.abstractfactory.plum.view.event.ViewAction;
import net.abstractfactory.plum.view.event.WebEvent;
import net.abstractfactory.plum.view.misc.Color;
import net.abstractfactory.plum.view.misc.Font;
import net.abstractfactory.plum.view.misc.FontWeight;
import net.abstractfactory.plum.view.misc.TextDecoration;
import net.abstractfactory.plum.view.web.CSSAttribute;
import net.abstractfactory.plum.view.web.CSSAttributes;
public abstract class AbstractWebComponent extends TreeNode implements
WebComponent {
protected String id;
protected Element styleElement;
protected Element htmlOuterElement;
protected Element htmlInnerElement;
protected Component component;
protected boolean changed = false;
private String ownHash;
private String childrenIdsHash;
public AbstractWebComponent(String id, Component component) {
this.id = id;
this.component = component;
}
/**
* it should be called after all other required parameters are set. in case
* subclass needs extra parameters than this constructors need.
*/
public void init() {
createHtmlElement();
updateIdInHtml(id);
// style
CSSAttributes attrs = createCommonStyles();
applyStyle(htmlOuterElement, attrs);
if (getComponent().isDisabled())
htmlOuterElement.attr("disabled", "disabled");
}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
this.id = id;
updateIdInHtml(id);
}
protected void updateIdInHtml(String id) {
if (id != null)
htmlOuterElement.attr("id", id);
}
@Override
public Component getComponent() {
return component;
}
@Override
public abstract void createHtmlElement();
public Element getStyleElement() {
return styleElement;
}
@Override
public Element getHtmlOuterElement() {
return htmlOuterElement;
}
/**
* used by addChild()
*
* @return
*/
protected Element getHtmlInnerElementForNewChild() {
return htmlInnerElement;
}
protected String getFullInputName(String shortName) {
return String.format("%s_%s", getId(), shortName);
}
@Override
public void addChild(TreeNode node) {
Element container = getHtmlInnerElementForNewChild();
super.addChild(node);
// create HTML DOM
WebComponent child = (WebComponent) node;
container.appendChild(child.getHtmlOuterElement());
}
protected String null2Empty(String str) {
if (str == null)
str = "";
return str;
}
protected Document loadFromResource(String name) {
InputStream stream = getClass().getResourceAsStream(name);
try {
Document doc = Jsoup.parse(stream, "utf-8", "");
return doc;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* event from browser
*
* @param name
* @param parameters
*/
public ViewAction processEvent(WebEvent event,
ListValueMap parameters) {
return processEvent(event, parameters.toSingleValueMap());
}
public ViewAction processEvent(WebEvent event,
Map parameters) {
throw new RuntimeException("not implemented");
}
/**
* subclass should find the file or image object by the short name.
*
* @param req
* @param response
* @param shortName
*/
@Override
public void writeFile(HttpServletRequest req, HttpServletResponse response,
String shortName) throws IOException {
throw new RuntimeException("not supported");
}
/**
* response with file(image, ...)
*/
protected void writeFile(HttpServletRequest req,
HttpServletResponse response, File file) throws IOException {
if (file == null)
return;
// modifies response
response.setContentType(file.getContentType());
response.setContentLength((int) file.getSize());
// forces download
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"",
file.getName());
response.setHeader(headerKey, headerValue);
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
InputStream inStream = file.getInputStream();
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inStream.close();
outStream.close();
}
@Override
public WebComponent getParentWebComponent() {
return (WebComponent) getParent();
}
public List getChildrenWebComponents() {
List webComponentList = new ArrayList();
for (TreeNode node : getChildren()) {
webComponentList.add((WebComponent) node);
}
return webComponentList;
}
@Override
public void replaceChild(WebComponent oldChild, WebComponent newChild) {
int index = getChildren().indexOf(oldChild);
getChildren().set(index, (TreeNode) newChild);
}
/**
* common style of component, such as font and color
*
* @return
*/
protected CSSAttributes createCommonStyles() {
Component comp = getComponent();
CSSAttributes attrs = new CSSAttributes();
if (!comp.isVisible()) {
attrs.add(new CSSAttribute("display", "none"));
}
Font font = comp.getFont();
if (font != null) {
if (font.getWeight() == FontWeight.BOLD)
attrs.add(new CSSAttribute("font-weight", "bold"));
if (font.getSize() != null)
attrs.add(new CSSAttribute("font-size", font.getSize()));
}
TextDecoration textDecoration = comp.getTextDecoration();
if (textDecoration != null) {
attrs.add(new CSSAttribute("text-decoration", textDecoration
.getCssValue()));
}
Color color = comp.getColor();
if (color != null) {
attrs.add(new CSSAttribute("color", "#" + color.getAsHex()));
}
Color backgroundColor = comp.getBackgroundColor();
if (backgroundColor != null) {
attrs.add(new CSSAttribute("background-color", "#"
+ backgroundColor.getAsHex()));
}
Length width = comp.getWidth();
if (width != null) {
attrs.add(new CSSAttribute("width", width.getCssExpr()));
}
Length height = comp.getHeight();
if (height != null) {
attrs.add(new CSSAttribute("height", height.getCssExpr()));
}
Border[] borders = comp.getBorders();
if (borders != null) {
if (borders.length != 4)
throw new RuntimeException(
"length of borders must be 4 if not null");
attrs.add(createBorderAttribute(BorderDirection.LEFT, borders[0]));
attrs.add(createBorderAttribute(BorderDirection.TOP, borders[1]));
attrs.add(createBorderAttribute(BorderDirection.RIGHT, borders[2]));
attrs.add(createBorderAttribute(BorderDirection.BOTTOM, borders[3]));
} else {
Border border = comp.getBorder();
if (border != null) {
attrs.add(createBorderAttribute(null, border));
}
}
return attrs;
}
private CSSAttribute createBorderAttribute(BorderDirection direction,
Border border) {
String value = String.format("%dpx %s #%s", border.getWidth(), border
.getStyle().name().toLowerCase(), border.getColor().getAsHex());
String name;
if (direction == null) {
name = "border";
} else {
name = "border-" + direction.name().toLowerCase();
}
CSSAttribute attr = new CSSAttribute(name, value);
return attr;
}
protected void applyStyle(Element element, CSSAttributes attrs) {
if (!attrs.isEmpty())
element.attr("style", attrs.toCssText());
}
protected void applyEvents(Element element, String inputName, String event) {
Component comp = getComponent();
if (comp.containsListener(Button.EVENT_CLICK)) {
String onclick = String.format("_plum_post('%s','%s','%s')",
getId(), inputName, event);
element.attr("onclick", onclick);
}
}
public String calcHash() {
return DigestUtils.md5Hex(getId() + htmlOuterElement.outerHtml());
}
public String calcHashOfChildrenId() {
StringBuilder sb = new StringBuilder();
for (TreeNode node : getChildren()) {
AbstractWebComponent awc = (AbstractWebComponent) node;
sb.append(awc.getId());
}
return DigestUtils.md5Hex(sb.toString());
}
public String getOwnHash() {
return ownHash;
}
public void setOwnHash(String ownHash) {
this.ownHash = ownHash;
}
public String getChildrenIdsHash() {
return childrenIdsHash;
}
public void setChildrenIdsHash(String childrenIdsHash) {
this.childrenIdsHash = childrenIdsHash;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy