All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.abstractfactory.plum.view.web.component.AbstractWebComponent Maven / Gradle / Ivy

There is a newer version: 0.3.21
Show newest version
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