/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.jsf.vpe.richfaces.template;
import java.util.ArrayList;
import java.util.List;
import org.jboss.tools.jsf.vpe.richfaces.ComponentUtil;
import org.jboss.tools.jsf.vpe.richfaces.RichFacesTemplatesActivator;
import org.jboss.tools.vpe.editor.context.VpePageContext;
import org.jboss.tools.vpe.editor.template.VpeAbstractTemplate;
import org.jboss.tools.vpe.editor.template.VpeChildrenInfo;
import org.jboss.tools.vpe.editor.template.VpeCreationData;
import org.jboss.tools.vpe.editor.template.expression.VpeExpression;
import org.jboss.tools.vpe.editor.template.expression.VpeExpressionException;
import org.jboss.tools.vpe.editor.util.HTML;
import org.jboss.tools.vpe.editor.util.VisualDomUtil;
import org.jboss.tools.vpe.editor.util.VpeClassUtil;
import org.mozilla.interfaces.nsIDOMDocument;
import org.mozilla.interfaces.nsIDOMElement;
import org.mozilla.interfaces.nsIDOMNode;
import org.mozilla.interfaces.nsIDOMNodeList;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
public class RichFacesSubTableTemplate extends VpeAbstractTemplate {
private static final String DEAFAULT_CELL_CLASS = "dr-subtable-cell"; //$NON-NLS-1$
private static List<String> rowClasses;
private static List<String> columnClasses;
private static final String ST_HEADER_CLASS = "dr-subtable-header rich-subtable-header";
private static final String ST_HEADER_CONTINUE_CLASS = "dr-subtable-header-continue rich-subtable-header-continue";
private static final String ST_FOOTER_CLASS = "dr-subtable-footer rich-subtable-footer";
private static final String ST_FOOTER_CONTINUE_CLASS = "dr-subtable-footer-continue rich-subtable-footer-continue";
/** @deprecated no one another template should know about this template */
public static final RichFacesSubTableTemplate DEFAULT_INSTANCE = new RichFacesSubTableTemplate();
public RichFacesSubTableTemplate() {
super();
}
public VpeCreationData encodeSubTable(final VpePageContext pageContext,
VpeCreationData creationData, final Element sourceElement,
final nsIDOMDocument visualDocument, nsIDOMElement parentVisualNode) {
if(creationData!=null) {
/*
* Encode header
*/
encodeHeader(pageContext, creationData, sourceElement, visualDocument, parentVisualNode);
}
initClasses(sourceElement, null);
nsIDOMElement curTr = visualDocument.createElement(HTML.TAG_TR);
if (parentVisualNode == null) {
parentVisualNode = curTr;
}
VisualDomUtil.copyAttributes(sourceElement, curTr);
boolean header = false;
boolean footer = false;
int curRow = 0;
int curColumn = 0;
if(isHeader(sourceElement)) {
curTr.setAttribute(HTML.ATTR_CLASS, getHeaderClass());
final String style = getHeaderBackgoundImgStyle();
if(style!=null) {
curTr.setAttribute(HTML.ATTR_STYLE, style);
}
header = true;
} else if(isFooter(sourceElement)) {
curTr.setAttribute(HTML.ATTR_CLASS, getFooterClass());
footer = true;
} else {
curTr.setAttribute(HTML.ATTR_CLASS, getRowClass(curRow));
}
if(creationData==null) {
// Method was called from create()
creationData = new VpeCreationData(curTr);
} else {
// Method was called from dataTable
parentVisualNode.appendChild(curTr);
}
creationData.addChildrenInfo(new VpeChildrenInfo(null));
// Create mapping to Encode body
VpeChildrenInfo trChildrenInfo = new VpeChildrenInfo(curTr);
final List<Node> children = ComponentUtil.getChildren(sourceElement);
for (final Node child : children) {
if (child.getNodeType() == Node.ELEMENT_NODE) {
String nodeName = child.getNodeName();
if (nodeName.endsWith(':' + RichFaces.TAG_COLUMN) ||
nodeName.endsWith(':' + RichFaces.TAG_COLUMNS)) {
if (RichFacesColumnTemplate.isBreakBefore(child)) {
curRow++;
curColumn = 0;
curTr = visualDocument.createElement(HTML.TAG_TR);
VisualDomUtil.copyAttributes(sourceElement, curTr);
if (header) {
curTr.setAttribute(HTML.ATTR_CLASS, getHeaderContinueClass());
} else if(footer) {
curTr.setAttribute(HTML.ATTR_CLASS, getFooterContinueClass());
} else {
curTr.setAttribute(HTML.ATTR_CLASS, getRowClass(curRow));
}
parentVisualNode.appendChild(curTr);
trChildrenInfo = new VpeChildrenInfo(curTr);
creationData.addChildrenInfo(trChildrenInfo);
}
final VpeChildrenInfo innerTdChildrenInfo = new VpeChildrenInfo(curTr);
creationData.addChildrenInfo(innerTdChildrenInfo);
innerTdChildrenInfo.addSourceChild(child);
curColumn++;
} else {
trChildrenInfo.addSourceChild(child);
}
}
}
if(parentVisualNode!=null) {
// Encode footer
encodeFooter(pageContext, creationData, sourceElement,
visualDocument, parentVisualNode);
}
return creationData;
}
/** Adds necessary attributes to its children.*/
@Override
public void validate(final VpePageContext pageContext, final Node sourceNode,
final nsIDOMDocument visualDocument, final VpeCreationData creationData) {
initClasses(sourceNode, pageContext);
nsIDOMNode visualNode = creationData.getNode();
/*
* https://jira.jboss.org/jira/browse/JBIDE-4311
* Tag name can be in any case.
*/
if (visualNode != null && visualNode.getNodeName().equalsIgnoreCase(HTML.TAG_TBODY)) {
// we are called by VpeVisualDomBuilder
addStylesToCells(visualDocument, visualNode);
} else {
RuntimeException e = new RuntimeException("This is probably a bug. The main tag of subTable shuld be 'TBODY'.");//$NON-NLS-1$
RichFacesTemplatesActivator.getPluginLog().logError(e);
}
}
/**
* Adds HTML style classes names to all TDs from the <code>rowsContainer</code>
* according to <code>columnClasses</code> attribute of the tag.
*/
private void addStylesToCells(nsIDOMDocument visualDocument, nsIDOMNode rowsContainer) {
nsIDOMNodeList rowsContainerChildren = rowsContainer.getChildNodes();
for (int j = 0; j < rowsContainerChildren.getLength(); j++) {
nsIDOMNode tBodyChild = rowsContainerChildren.item(j);
if (tBodyChild.getNodeType() == nsIDOMNode.ELEMENT_NODE && HTML.TAG_TR.equalsIgnoreCase(tBodyChild.getNodeName())) {
nsIDOMNodeList rowChildren = tBodyChild.getChildNodes();
int column = 0;
for (int i = 0; i < rowChildren.getLength(); i++) {
final nsIDOMNode visualChild = rowChildren.item(i);
if ( visualChild.getNodeType() == nsIDOMNode.ELEMENT_NODE && HTML.TAG_TD.equalsIgnoreCase(visualChild.getNodeName()) ) {
final nsIDOMNode tableCell = visualChild;
nsIDOMNode columnStyle = tableCell.getAttributes().getNamedItem(HTML.ATTR_CLASS);
if (columnStyle == null) {
columnStyle = visualDocument.createAttribute(HTML.ATTR_CLASS);
}
columnStyle.setNodeValue(columnStyle.getNodeValue() + HTML.VALUE_CLASS_DELIMITER
+ getColumnClass(column));
column++;
}
}
}
}
}
public VpeCreationData create(final VpePageContext pageContext, final Node sourceNode, final nsIDOMDocument visualDocument) {
final Element sourceElement = (Element)sourceNode;
final nsIDOMElement tbody = visualDocument.createElement(HTML.TAG_TBODY);
VpeCreationData creationData = new VpeCreationData(tbody);
creationData = encodeSubTable(pageContext, creationData, sourceElement,
visualDocument, tbody);
return creationData;
}
protected void encodeHeader(final VpePageContext pageContext, final VpeCreationData creationData, final Element sourceElement, final nsIDOMDocument visualDocument, final nsIDOMElement parentVisualNode) {
encodeHeaderOrFooter(
pageContext,
creationData,
sourceElement,
visualDocument,
parentVisualNode,
RichFaces.NAME_FACET_HEADER,
"dr-subtable-header rich-subtable-header", //$NON-NLS-1$
"dr-subtable-headercell rich-subtable-headercell"); //$NON-NLS-1$
}
protected void encodeFooter(final VpePageContext pageContext, final VpeCreationData creationData, final Element sourceElement, final nsIDOMDocument visualDocument, final nsIDOMElement parentVisualNode) {
encodeHeaderOrFooter(
pageContext,
creationData,
sourceElement,
visualDocument,
parentVisualNode,
RichFaces.NAME_FACET_FOOTER,
"dr-subtable-footer rich-subtable-footer", //$NON-NLS-1$
"dr-subtable-footercell rich-subtable-footercell"); //$NON-NLS-1$
}
protected void encodeHeaderOrFooter(final VpePageContext pageContext,
final VpeCreationData creationData, final Element sourceElement,
final nsIDOMDocument visualDocument,
final nsIDOMElement parentVisualNode, final String facetName,
final String trClass, final String tdClass) {
final ArrayList<Element> columns = RichFaces.getColumns(sourceElement);
// final ArrayList<Element> columnsHeaders =
// ComponentUtil.getColumnsWithFacet(columns, facetName);
final boolean hasColumnWithFacet = RichFaces.hasColumnWithFacet(columns, facetName);
if (hasColumnWithFacet) {
final nsIDOMElement tr = visualDocument.createElement(HTML.TAG_TR);
parentVisualNode.appendChild(tr);
final String styleClass = trClass;
if (styleClass != null) {
tr.setAttribute(HTML.ATTR_CLASS, styleClass);
}
RichFacesDataTableTemplate.encodeHeaderOrFooterFacets(pageContext,
creationData, tr, visualDocument, columns, tdClass, null,
facetName, HTML.TAG_TD);
}
}
private boolean isHeader(final Element sourceElement) {
return icludedInFacet(sourceElement, RichFaces.NAME_FACET_HEADER);
}
private boolean isFooter(final Element sourceElement) {
return icludedInFacet(sourceElement, RichFaces.NAME_FACET_FOOTER);
}
private boolean icludedInFacet(final Element sourceElement, final String facetName) {
final Node parent = sourceElement.getParentNode();
return parent!=null && ComponentUtil.isFacet(parent, facetName);
}
protected String getHeaderClass() {
return ST_HEADER_CLASS;
}
protected String getHeaderContinueClass() {
return ST_HEADER_CONTINUE_CLASS;
}
protected String getFooterClass() {
return ST_FOOTER_CLASS;
}
protected String getFooterContinueClass() {
return ST_FOOTER_CONTINUE_CLASS;
}
protected String getRowClass(final int row) {
String rowClass = DEAFAULT_CELL_CLASS;
if (rowClasses != null) {
final int rowClassesSize = rowClasses.size();
if(rowClassesSize > 0) {
rowClass = rowClasses.get(row % rowClassesSize);
}
}
return rowClass;
}
private String getColumnClass(final int column) {
String columnClass = DEAFAULT_CELL_CLASS;
if (columnClasses != null) {
final int columnClassesSize = columnClasses.size();
if (columnClassesSize > 0) {
columnClass = columnClasses.get(column % columnClassesSize);
}
}
return columnClass;
}
private void initClasses(final Node sourceNode, final VpePageContext pageContext) {
final VpeExpression exprRowClasses = RichFaces.getExprRowClasses();
final VpeExpression exprColumnClasses = RichFaces.getExprColumnClasses();
try {
rowClasses = VpeClassUtil.getClasses(exprRowClasses, sourceNode,
pageContext);
columnClasses = VpeClassUtil.getClasses(exprColumnClasses, sourceNode,
pageContext);
} catch (final VpeExpressionException e) {
throw new RuntimeException(e);
}
}
protected String getHeaderBackgoundImgStyle() {
return null;
}
/* (non-Javadoc)
* @see org.jboss.tools.vpe.editor.template.VpeAbstractTemplate#isRecreateAtAttrChange(org.jboss.tools.vpe.editor.context.VpePageContext, org.w3c.dom.Element, org.mozilla.interfaces.nsIDOMDocument, org.mozilla.interfaces.nsIDOMElement, java.lang.Object, java.lang.String, java.lang.String) */
@Override
public boolean recreateAtAttrChange(final VpePageContext pageContext,
final Element sourceElement, final nsIDOMDocument visualDocument,
final nsIDOMElement visualNode, final Object data, final String name, final String value) {
return true;
}
/* (non-Javadoc)
* @see org.jboss.tools.vpe.editor.template.VpeAbstractTemplate#getNodeForUpdate(org.jboss.tools.vpe.editor.context.VpePageContext, org.w3c.dom.Node, org.mozilla.interfaces.nsIDOMNode, java.lang.Object) */
@Override
public Node getNodeForUpdate(VpePageContext pageContext, Node sourceNode,
nsIDOMNode visualNode, Object data) {
Node parent = sourceNode.getParentNode();
return parent;
}
}