/*******************************************************************************
* Copyright (c) 2007-2008 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
*
* Contributor:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.jsf.vpe.richfaces.template;
import static org.jboss.tools.vpe.xulrunner.util.XPCOM.queryInterface;
import java.util.List;
import org.jboss.tools.vpe.editor.context.VpePageContext;
import org.jboss.tools.vpe.editor.template.VpeAbstractTemplate;
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.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.Node;
/**
* Class {@code RichFacesDataTableStyleClassesApplier} should be used in templates
* of tags that support attributes {@code 'rowClasses'} and {@code 'columnClasses'}.
* <P/>
* It expects it is used in pair with {@link RichFacesDataTableChildrenEncoder}.
*
* @author yradtsevich
*/
public class RichFacesDataTableStyleClassesApplier {
private final List<String> rowClasses;
private final List<String> columnClasses;
/**
* Constructs {@code RichFacesDataTableStyleClassesApplier}.
*
* @param visualDocument an object of {@link nsIDOMDocument}
* @param pageContext an object of {@link VpePageContext}
* @param sourceNode an object of a tag that could have
* attributes {@code 'rowClasses'} and {@code 'columnClasses'}.
*/
public RichFacesDataTableStyleClassesApplier(final nsIDOMDocument visualDocument,
final VpePageContext pageContext, final Node sourceNode) {
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);
}
}
/**
* Applies style-classes specified in attributes {@code 'rowClasses'} and
* {@code 'columnClasses'} of {@code sourceNode} to the {@code targetTable}.
* <P/>
* This method should be used in
* {@link VpeAbstractTemplate#validate(VpePageContext, Node, nsIDOMDocument, VpeCreationData) validate()}
* method of a template after
* {@link RichFacesDataTableChildrenEncoder#validateChildren(VpePageContext, Node, nsIDOMDocument, VpeCreationData) RichFacesDataTableChildrenEncoder.validateChildren()}
* is called.
* <P/>
* The basic idea of the method is to add appropriate rowClasses only
* to the direct TR children of the table and add appropriate columnClasses
* only to direct TD children of that TRs. It gives us opportunity to separate
* TRs and TDs that created by the tag directly from TRs and TDs created
* by the tag's children.
*/
public void applyClasses(final nsIDOMElement targetTable) {
final nsIDOMNodeList tableChildren = targetTable.getChildNodes();
int rowIndex = 0;
final int tableChildrenLength = (int) tableChildren.getLength();
for (int i = 0; i < tableChildrenLength; i++) {
final nsIDOMNode tableChild = tableChildren.item(i);
if (tableChild.getNodeType() == nsIDOMNode.ELEMENT_NODE
&& HTML.TAG_TR.equalsIgnoreCase( tableChild.getNodeName() )) {
final nsIDOMElement row =
queryInterface(tableChild, nsIDOMElement.class);
applyClass(rowClasses, row, rowIndex);
applyClassesToCells(row);
rowIndex++;
}
}
}
/**
* Applies style-classes specified in attribute {@code 'columnClasses'}
* of {@code sourceNode} to the {@code row}.
*/
private void applyClassesToCells(final nsIDOMElement row) {
final int columnClassesSize = columnClasses.size();
if (columnClassesSize > 0) {
final nsIDOMNodeList rowChildren = row.getChildNodes();
int columnIndex = 0;
int rowChildrenLength = (int)rowChildren.getLength();
for (int j = 0; j < rowChildrenLength; j++) {
final nsIDOMNode rowChild = rowChildren.item(j);
if (rowChild.getNodeType() == nsIDOMNode.ELEMENT_NODE
&& HTML.TAG_TD.equalsIgnoreCase( rowChild.getNodeName() )) {
final nsIDOMElement cell =
queryInterface(rowChild, nsIDOMElement.class);
applyClass(columnClasses, cell, columnIndex);
columnIndex++;
}
}
}
}
/**
* Applies appropriate style-class from the list {@code classes} to the
* {@code element} (a row or a cell) position of that is {@code elementIndex}.
*/
private static void applyClass(final List<String> classes, final nsIDOMElement element,
int elementIndex) {
int classesSize = classes.size();
if (classesSize > 0) {
final String clazz = classes.get(elementIndex % classesSize);
String actualClass = element.hasAttribute(HTML.ATTR_CLASS) ? element.getAttribute(HTML.ATTR_CLASS) + HTML.VALUE_CLASS_DELIMITER + clazz : clazz;
element.setAttribute(HTML.ATTR_CLASS, actualClass);
}
}
}