/*
* 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.tools.scanner.template;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cruxframework.crux.core.declarativeui.template.TemplateException;
import org.cruxframework.crux.core.utils.URLUtils;
import org.cruxframework.crux.scanner.Scanners;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
*
* @author Thiago da Rosa de Bustamante
*
*/
public class Templates
{
private static final Log logger = LogFactory.getLog(Templates.class);
private static Map<String, Set<String>> registeredLibraries = new HashMap<String, Set<String>>();
private static boolean starting = false;
private static Map<String, Document> templates = new HashMap<String, Document>();
private static Map<String, Set<String>> widgetTemplates = new HashMap<String, Set<String>>();
private static Map<String, URL> foundTemplates = new HashMap<String, URL>();
private static boolean initialized = false;
/**
*
* @return
*/
public static Set<String> getRegisteredLibraries()
{
if (!initialized)
{
initialize();
}
return registeredLibraries.keySet();
}
/**
*
* @param library
* @return
*/
public static Set<String> getRegisteredLibraryWidgetTemplates(String library)
{
if (!initialized)
{
initialize();
}
return widgetTemplates.get(library);
}
/**
*
* @param library
* @return
*/
public static Set<String> getRegisteredLibraryTemplates(String library)
{
if (!initialized)
{
initialize();
}
return registeredLibraries.get(library);
}
/**
*
* @param library
* @param id
* @return
*/
public static Document getTemplate(String library, String id)
{
return getTemplate(library, id, false);
}
/**
*
* @param library
* @param id
* @return
*/
public static Document getTemplate(String library, String id, boolean clone)
{
if (!initialized)
{
initialize();
}
Document document = templates.get(library+"_"+id);
if (document != null)
{
document = (Document) document.cloneNode(true);
}
return document;
}
/**
*
*/
public static synchronized void initialize()
{
if (initialized)
{
return;
}
starting = true;
templates.clear();
widgetTemplates.clear();
registeredLibraries.clear();
foundTemplates.clear();
Scanners.resetScanner(TemplatesScanner.class);
logger.info("Searching for template files.");
TemplatesScanner.getInstance().scanArchives();
initializeWidgetTemplates();
setInitialized();
}
/**
*
*/
public static void restart()
{
initialized = false;
initialize();
}
/**
*
*/
public static void reset()
{
initialized = false;
templates.clear();
widgetTemplates.clear();
registeredLibraries.clear();
foundTemplates.clear();
}
static void setInitialized()
{
starting = false;
initialized = true;
}
/**
* @param parentElement
* @return
*/
static List<Element> extractChildrenElements(Element parentElement)
{
List<Element> result = new ArrayList<Element>();
NodeList childNodes = parentElement.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++)
{
Node node = childNodes.item(i);
switch (node.getNodeType())
{
case Node.COMMENT_NODE:
//ignore node
break;
case Node.TEXT_NODE:
Text textNode = (Text) node;
if (textNode.getWholeText().trim().length() > 0)
{
return null;
}
break;
case Node.ELEMENT_NODE:
result.add((Element) node);
break;
default:
return null;
}
}
return result;
}
/**
* @return
*/
public static boolean isStarting(){
return starting;
}
/**
* @param template
* @return
*/
static boolean isWidgetTemplate(Document template)
{
boolean isWidget = false;
if (template != null)
{
Element templateElement = template.getDocumentElement();
List<Element> children = extractChildrenElements(templateElement);
if (children != null && children.size() == 1)
{
Element element = children.get(0);
String namespaceURI = element.getNamespaceURI();
if (namespaceURI != null)
{
if (namespaceURI.startsWith("http://www.cruxframework.org/crux/"))
{
isWidget = true;
}
else if (namespaceURI.startsWith("http://www.cruxframework.org/templates/"))
{
String library = namespaceURI.substring("http://www.cruxframework.org/templates/".length());
Document refTemplate = getTemplate(library, element.getLocalName());
isWidget = isWidgetTemplate(refTemplate);
}
}
}
}
return isWidget;
}
/**
*
* @param templateId
* @param template
*/
static void registerTemplate(String templateId, Document template, URL templateURL)
{
Element templateElement = template.getDocumentElement();
String library = templateElement.getAttribute("library");
String key = library+"_"+templateId;
if (templates.containsKey(key))
{
URL registeredURL = foundTemplates.get(key);
if (!URLUtils.isIdenticResource(templateURL, registeredURL, templateId+".template.xml"))
{
throw new TemplateException("Duplicated template found. Library: ["+library+"]. Template: ["+templateId+"].");
}
}
if (!registeredLibraries.containsKey(library))
{
registeredLibraries.put(library, new HashSet<String>());
}
registeredLibraries.get(library).add(templateId);
templates.put(key, template);
foundTemplates.put(key, templateURL);
}
/**
*
*/
private static void initializeWidgetTemplates()
{
for (Entry<String, Document> entry : templates.entrySet())
{
if (isWidgetTemplate(entry.getValue()))
{
String templateKey = entry.getKey();
String[] templateIdParts = templateKey.split("_");
Set<String> templates = widgetTemplates.get(templateIdParts[0]);
if (templates == null)
{
templates = new HashSet<String>();
widgetTemplates.put(templateIdParts[0], templates);
}
templates.add(templateIdParts[1]);
}
}
}
}