/*
* Copyright 2011 cruxframework.org.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cruxframework.crux.core.declarativeui.template;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* @author Thiago da Rosa de Bustamante
*
*/
public class TemplateParser
{
private XPathExpression templateAttributesExpression;
private XPathExpression templateChildrenNameExpression;
private XPathExpression templateChildrenExpression;
/**
*
*/
public TemplateParser()
{
XPathFactory factory = XPathFactory.newInstance();
XPath findTemplates = factory.newXPath();
findTemplates.setNamespaceContext(new NamespaceContext()
{
public String getNamespaceURI(String prefix)
{
return "http://www.cruxframework.org/templates";
}
public String getPrefix(String namespaceURI)
{
return "t";
}
public Iterator<?> getPrefixes(String namespaceURI)
{
List<String> prefixes = new ArrayList<String>();
prefixes.add("t");
return prefixes.iterator();
}
});
try
{
templateAttributesExpression = findTemplates.compile("//@*[contains(., '#{')] | //text()[contains(., '#{')]");
templateChildrenNameExpression = findTemplates.compile("//t:section/@name");
templateChildrenExpression = findTemplates.compile("//t:section");
}
catch (XPathExpressionException e)
{
throw new TemplateException("Error initializing template parser.", e);
}
}
/**
*
* @param template
*/
public Set<String> getParameters(Document template)
{
Set<Node> parametersNodes = getParametersNodes(template);
Set<String> attributes = new HashSet<String>();
for (Node node : parametersNodes)
{
String attrValue = node.getNodeValue();
if (attrValue.contains("#{"))
{
extractParameterNames(attrValue, attributes);
}
}
return attributes;
}
/**
*
* @param template
*/
public Set<Node> getParametersNodes(Document template)
{
try
{
NodeList nodes = (NodeList)templateAttributesExpression.evaluate(template, XPathConstants.NODESET);
Set<Node> attributes = new HashSet<Node>();
for (int i = 0; i < nodes.getLength(); i++)
{
Node attribute = nodes.item(i);
String attrValue = attribute.getNodeValue();
if (attrValue.contains("#{"))
{
attributes.add(attribute);
}
}
return attributes;
}
catch (XPathExpressionException e)
{
throw new TemplateException("Error generating attributes for template ["+template.getLocalName()+"].", e);
}
}
/**
*
* @param template
* @return
*/
public Set<String> getSections(Document template)
{
try
{
NodeList sections = (NodeList) templateChildrenNameExpression.evaluate(template.getDocumentElement(), XPathConstants.NODESET);
Set<String> children = new HashSet<String>();
if (sections != null && sections.getLength() > 0)
{
for (int i=0; i< sections.getLength(); i++)
{
Node section = sections.item(i);
String sectionName = section.getNodeValue();
children.add(sectionName);
}
}
return children;
}
catch (XPathExpressionException e)
{
throw new TemplateException("Error generating children for template ["+template.getLocalName()+"]", e);
}
}
/**
*
* @param template
* @return
*/
public Map<String, Node> getSectionElements(Document template)
{
try
{
NodeList sections = (NodeList) templateChildrenExpression.evaluate(template.getDocumentElement(), XPathConstants.NODESET);
Map<String, Node> children = new HashMap<String, Node>();
if (sections != null && sections.getLength() > 0)
{
for (int i=0; i< sections.getLength(); i++)
{
Node section = sections.item(i);
String sectionName = ((Element)section).getAttribute("name");
children.put(sectionName, section);
}
}
return children;
}
catch (XPathExpressionException e)
{
throw new TemplateException("Error generating children for template ["+template.getLocalName()+"]", e);
}
}
/**
*
* @param attrValue
* @param attributes
*/
public void extractParameterNames(String attrValue, Set<String> attributes)
{
int indexStarParam = attrValue.indexOf("#{");
while (indexStarParam >= 0)
{
attrValue = attrValue.substring(indexStarParam+2);
int indexEndParam = attrValue.indexOf("}");
if (indexEndParam >= 0)
{
String param = attrValue.substring(0, indexEndParam);
attributes.add(param);
attrValue = attrValue.substring(indexEndParam+1);
indexStarParam = attrValue.indexOf("#{");
}
else
{
break;
}
}
}
}